Antibiotic's NOTES
1.数组的初始化
int m;
cin>>m;
int a[m];//会导致错误(静态)
int a[100]={-1}//会变成这样:{-1,146,-126,534...}(只初始化了第一个数,其他会随机分配)
memset(a,0,100,sizeof(a));//可以把快速全部设成0(0换成-1也可以)❗换成1不行,不会设成1❌
bool b[100];
memset(b,0,sizeof(b));//全部设成0
memset(b,1,sizeof(b));//可以全部设成1✅
memset(b,-1,sizeof(b));//不会设成-1,而是255
注:memset的数据均使用Ubuntu下的g++命令测试(这玩意好像在不同的操作系统,不同编译器下的结果不同)
2.不定长度数字的读入
cin遇到换行不会停止,除非输入了其他类型
或者遇到了文件结束符EOF(在Windows下是Ctrl+Z,在Unix是Ctrl+D)
//BUG
int num,nums[10],i=0;
while (~scanf()) { //不会停止,除非有字符串
nums[i]=num;
i++;
}
补充:scanf的一些用法
-
scanf("%[^\n]",s);遇到换行符时才停止读入(这指的是一次读入,作为字符串)scanf()中[]里面^后面就是你要停止读入的字符,如把\n换成s意思就是遇到s就停止读入同时在
^的后面可以放很多的字符,例如scanf("%[^sdf]",s);,意思就是遇到里面的任一个字符都停止读入。 -
while(scanf()!=EOF)可以实现一直输入,一直到EOF(end of file,文件结束符),一般OJ的测评里输入的最后都会有这个
3.位运算
注意!位运算优先级别很低,会先计算 + -
//BUG
int i=3;
i=i<<3+i<<1;//在这里会先算3+i
//正确写法
int i=3;
i=(i<<3)+(i<<1);
4.关于输入输出的卡常
默认的时候,cin与stdin总是保持同步的,导致效率比较低
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
只要加上这一行,cin可以达到scanf的速度(但是scanf好像更快一些),它可以禁用同步
不要用endl!!!特别慢!!!(cout << '\n')
注意:cin,cout不要与getchar,scanf,printf一起使用,同步流的过程会变得特别慢!!
5.getchar()的使用
getchar()会把换行符也当作一个字符,遇到换行,需要多写一个没用的getchar(),跳过换行符,就能继续读下一行了
6.务必检查数据的输入及初始化
7.sizeof()的使用
sizeof()是一个操作符(operator)
#include <stdio.h>
void main() {
int a = 10;
char b = 'b';
short c = 2;
long d = 9;
float e = 6.29f;
double f = 95.0629;
int arr[] = { 1,2,3 };
char str[] = "hello";
double *p=&f;
int *i=&a;
//分别对各个变量使用sizeof运算
printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d,arr=%d,str=%d point_p=%d,point_i=%d\n",
sizeof(a), sizeof(b), sizeof(c), sizeof(d), sizeof(e), sizeof(f),
sizeof(arr), sizeof(str), sizeof(p), sizeof(i));
system("pause");
}
//输出的结果是:a=4,b=1,c=2,d=4,e=4,f=8,arr=12,str=6 point_p=4,point_i=4
sizeof()实际上是获取了数据在内存中所占用的存储空间,以字节为单位来计数
sizeof()是在编译时确定大小的,而动态分配是运行过程中得到大小的
8.memset()的使用
memset函数是对字节为单位进行赋值的
void *memset(void *s, int ch, size_t n);
函数解释:将s中前n个字节用ch[1]替换并返回s。
其实这里面的ch就是ASCII为ch的字符(见附录);
将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值
To continue:
sizeof()
memset()
9.自加++和自减--运算符
x++表示在使用x之后,使x的值加1,即x=x+1
++x表示使用x之前,先使x的值加1,即x=x+1
10.length()函数的返回值
string类size(), length()函数的返回值是无符号数
11.清空一个队列queue的几种方法
1
直接用空的队列赋值
queue <int> q1;
//process...
q1=queue <int> ();
2
遍历出队列
while(!Q.empty()) {
Q.pop();
}
3
使用swap(),这种是最高效的,定义clear,保持STL容器的标准
void clear(queue <int> &q) {
queue<int> empty;
swap(empty, q);
}
12.sort()高级用法
降序以及自定排序
sort()默认是升序排列,可以用如下方法使它降序排列
int cmp(int a,int b) {
return a>b;//降序排列,也可以实现其他的
}
int main() {
int nums[5] = {4, 2, 3, 1, 5};
sort(nums, nums+5, cmp);
return 0;
}
对于结构体等复杂结构的另一种操作
该操作比较有意思,通过重载操作符实现
见LINK(记得测试一下)
13.贪心的证明
一种重要的证明方法:邻项交换法
只要计算假如相邻的两项交换位置,会对答案产生的影响,分析是交换更优还是不交换更优
14.秦九韶算法
也叫霍纳算法,用于快速计算多项式的值
一般地,一元n次多项式的求值需要经过\(\dfrac{(n+1)\times n}{2}\)次乘法和\(n\)次加法,而秦九韶算法只需要\(n\)次乘法和\(n\)次加法,在人工计算时,一次大大简化了运算过程
具体实现:
把一个n次多项式
\(f(x)=a_nx^n+a_{n-1}x^{n-1}+\cdots+a_1x+a_0\)
改写成如下形式:
求多项式的值时,首先计算最内层括号内一次多项式的值,即
然后由内向外逐层计算一次多项式的值,即
这样,求\(n\)次多项式\(f(x)\)的值就转化为求\(n\)个一次多项式的值
结论:对于一个\(n\)次多项式,至多做\(n\)次乘法和\(n\)次加法
15.卡常技巧
减少取模运算
可以实现2s -> 500ms的优化
16.int main(int argc,char** argv)
argc是命令行总的参数个数
argv是命令行的每一个参数(字符数组)
char**相当于一个字符串数组
关于
char**,见这篇博客
这个赋值的过程是编译器完成的,我们只需要读入数据即可
e.g.
~$ test
# 这里是 argc 是 1(包括了命令名)
~$ test myarg1 myarg2
# 这里是 argc 就会是 3(包括了命令名和两个参数)
# argv[0] 的值就是 "test",argv[1] 的值就是 myarg1,argv[2] 的值就是 myarg2
17. 关于<<
\(1<<n\)中,若\(n\)为long long,仍然无法进行long long的运算,会越界;所以,必须要把\(11\)变成ll1<<n
\(2\) 的整次幂可以直接用位移,别用pow()
18.一定要注意取模的数据范围,有可能超的一定要记得取模!!!
19.emplace() 和 insert()
用于向vector容器中插入元素,其中emplace_back对应push_back,emplace_front对应push_front,emplace对应的是insert(但是不能一次插入多个元素)
为什么要使用emplace()呢?
速度比insert快,简单来说,emplace()在插入元素时,是在容器的制定位置直接构造元素,而不是先生成,在复制(或移动)到容器中去,所以推荐用emplace()
insert()是 \(O(N)\) 的!
20.,运算符
,可以把多条语句写在一起,但是要注意,return的前后都不能有,!!
21.CE的奇妙原因
search这个函数是在c++17的std命名空间中的,如果在搜索题用了这个写,就会CE(在c++11,c++14里面都不会有问题)
p.s. 貌似ACwing的默认c++标准就是17或者20
numbers是c++20标准中的,定义于命名空间std::numbers,如果在洛谷手残点了c++20,数组名又用了numbers,就会CE
next和prev是c++保留字,index是Linux下的C函数,不能随便用
next -> nxt prev -> prv/pre index -> idx
22.关于printf()
printf()必须严格对应数据类型,否则会出大问题
int res = 5;
printf("%.2f", res); //会输出0.00,有问题
printf("%.2f", res*1.0); //这样就没有问题了
注意:在printf()`中没有lf这个格式符,float和double都是f
如下表,printf()中的格式控制
| 数据类型 | 格式符 |
|---|---|
| int | %d |
| long long | %lld |
| float | %f |
| double | %f / %lf |
| char | %c. |
| 字符串(char数组) | %s |
| long double | %Lf. |
long double输入也是%Lf
23.指针的大小
指针的大小是8个字节!!!!
是int的的两倍!!!!
24. lower_bound & upper_bound
附录
ASCII码表

size_t是一个依赖于编译系统的值,一般定义为typedef unsigned int size_t↩︎

浙公网安备 33010602011771号