为什么突然放些这么水的东西?
我还是个C++小萌新,XD
【一 litTLE经验值】
1. C++里 自带pow(x,y) ,尤其是pow(x,0.333333)这种时候很有用。所以自己定义的快速幂最好别取名为pow。
2. c++的 /既有整除也有小数除。 记得用上(double) 或 加上.0
3. scanf("%c",&S) 若已经到文件末尾 scanf()=-1 否则scanf()=1 可以利用函数返回值判断文件末 这个函数返回的是scanf到的变量的个数
4. 用dev调试时,首先大部分电脑 应该都是用TDM-GCC 4.8.1 32-bit Debug 或者 是64-bit的 一般没啥能用release调试的。
而且,由于c++普遍的临时变量存在,调试时要把某个重名的变量删去再添加查看。。【日。】 而且要调试的话。不能直接放在磁盘目录下,会爆炸。要建文件夹。。
dev在调试到cin cout函数的时候会卡住,所以 我都用scanf printf
F7一行执行,F8进入当前行的函数(如果有)——与pascal相反。。。 按F5运行到下一个标红的行。
5. vector.size()是unsigned, -1<vector.size()是false,记得前面加(int)。
6. C++的sort 如sort(a+l,a+r+1,cmp); 若l>r是会出事的。。。记得if判掉(等于似乎是没事的)
7. 省选惨痛的经验。记得编译选项里开-Wall
8. 在devc++的编译选项里 加入 -Wl,--stack=100000000 可以防止系统栈爆炸
9. C++的define 很强大, 但是尤其是define lc (u<<1)时 不要忘了加括号 ,因为它是文本替换。(其实不论define什么都加括号是最稳的)
10. 莫名RE怎么办,目前遇到的调试到令人发疯的 原因有:BZOJ不能用C++的time函数 ,辣鸡OJ系统栈小的可怜(递归改成手写栈)。
11. 常用函数
unique的作用是“去掉”容器中相邻元素的重复元素,而返回值是去重之后的尾地址指针
lower_bound是返回[l,r)中第一个大于等于val的位置指针,而upper_bound是大于。
int a[4]={1,1,2,2};
int n=unique(a,a+4)-a; //n=2 ,剩余序列是 [0,2)
int t=lower_bound(a,a+4,2)-a; //t=2 ,第一个≥2的是a[2]
int t=upper_bound(a,a+4,-1)-a; //t=0 ,第一个>-1的是a[0]
int t=upper_bound(a,a+4,2)-a; //t=4 , 找不到则返回末尾地址
可以加cmp cmp定义为小于号(同sort). upper_bound(a+1,a+n+1,x,cmp)-a;
nth_element(a+1,a+k,a+n+1); //将第k小的元素放到第k位,其余的,左边比第k小,右边比第k大,但不一定有序。
12.二进制中挺有用的函数:
1 //返回前导的0的个数。 2 int __builtin_clz (unsigned int x) 3 //返回后面的0个个数,和__builtin_clz相对。 4 int __builtin_ctz (unsigned int x)
13. 注意,C++函数的传参是从右到左执行的,比如自己写一个函数add,然后add(read(),read(),read()); 配上快读(read),
读入的顺序是反的,比如输入顺序是1 2 3,而传参则是3 2 1。
另一个容易踩坑的,printf("%d%d",read(),read()); 也是从右往左
14. c++的 #include <bits/stdc++.h> 有1.6M!!
15. unsigned x; x>>k (<<也是一样的) k>=32是未定义行为。unsigned long long x; x>>k ,k>=64也是。手写bitset的时候,可能要特判!
16. iostream.h是C中的,iostream是C++中的 ; cstdio 是C++中的(继承自C,用namespace std) ,stdio.h是C中的。 其它的库也类似,.h一般是C的,c****一般是C++的
【卡常】{
- 把一系列与外界不相干的函数用struct封装起来,速度会变快。但是在struct里定义大数组,会变慢。
- 该用bool的用bool,用int会慢
- 少用operator
- 听说++x应该要比x++快? 听说 ?():()要比 if else快?
}
类型 |
比特(位)数 |
有效数字 |
数值范围 |
float |
32 |
6~7 |
-3.4*10^38~+3.4*10^38 |
double |
64 |
15~16 |
-1.7*10^-308~1.7*10^308 |
long double |
128/ |
18~19 |
-1.2*10^-4932~1.2*10^4932 |
【二 优先级】
放一个表格(转自http://www.cnblogs.com/ywl925/p/3710246.html)
记住c++里的 或 异或 & 优先级比 比较符号还低! <<和>>比+-*/低
优先级 | 操作符 | 描述 | 例子 | 结合性 |
---|---|---|---|---|
1 | () [] -> . :: ++ -- |
调节优先级的括号操作符 数组下标访问操作符 通过指向对象的指针访问成员的操作符 通过对象本身访问成员的操作符 作用域操作符 后置自增操作符 后置自减操作符 |
(a + b) / 4; array[4] = 2; ptr->age = 34; obj.age = 34; Class::age = 2; for( i = 0; i < 10; i++ ) ... for( i = 10; i > 0; i-- ) ... |
从左到右 |
2 | ! ~ ++ -- - + * & (type) sizeof |
逻辑取反操作符 按位取反(按位取补) 前置自增操作符 前置自减操作符 一元取负操作符 一元取正操作符 解引用操作符 取地址操作符 类型转换操作符 返回对象占用的字节数操作符 |
if( !done ) ... flags = ~flags; for( i = 0; i < 10; ++i ) ... for( i = 10; i > 0; --i ) ... int i = -1; int i = +1; data = *ptr; address = &obj; int i = (int) floatNum; int size = sizeof(floatNum); |
从右到左 |
3 | ->* .* |
在指针上通过指向成员的指针访问成员的操作符 在对象上通过指向成员的指针访问成员的操作符 |
ptr->*var = 24; obj.*var = 24; |
从左到右 |
4 | * / % |
乘法操作符 除法操作符 取余数操作符 |
int i = 2 * 4; float f = 10 / 3; int rem = 4 % 3; |
从左到右 |
5 | + - |
加法操作符 减法操作符 |
int i = 2 + 3; int i = 5 - 1; |
从左到右 |
6 | << >> |
按位左移操作符 按位右移操作符 |
int flags = 33 << 1; int flags = 33 >> 1; |
从左到右 |
7 | < <= > >= |
小于比较操作符 小于或等于比较操作符 大于比较操作符 大于或等于比较操作符 |
if( i < 42 ) ... if( i <= 42 ) ... if( i > 42 ) ... if( i >= 42 ) ... |
从左到右 |
8 | == != |
等于比较操作符 不等于比较操作符 |
if( i == 42 ) ... if( i != 42 ) ... |
从左到右 |
9 | & | 按位与操作符 | flags = flags & 42; | 从左到右 |
10 | ^ | 按位异或操作符 | flags = flags ^ 42; | 从左到右 |
11 | | | 按位或操作符 | flags = flags | 42; | 从左到右 |
12 | && | 逻辑与操作符 | if( conditionA && conditionB ) ... | 从左到右 |
13 | || | 逻辑或操作符 | if( conditionA || conditionB ) ... | 从左到右 |
14 | ? : | 三元条件操作符 | int i = (a > b) ? a : b; | 从右到左 |
15 | = += -= *= /= %= &= ^= |= <<= >>= |
赋值操作符 复合赋值操作符(加法) 复合赋值操作符(减法) 复合赋值操作符(乘法) 复合赋值操作符(除法) 复合赋值操作符(取余) 复合赋值操作符(按位与) 复合赋值操作符(按位异或) 复合赋值操作符(按位或) 复合赋值操作符(按位左移) 复合赋值操作符(按位右移) |
int a = b; a += 3; b -= 4; a *= 5; a /= 2; a %= 3; flags &= new_flags; flags ^= new_flags; flags |= new_flags; flags <<= 2; flags >>= 2; |
从右到左 |
16 | , | 逗号操作符 | for( i = 0, j = 0; i < 10; i++, j++ ) ... | 从左到右 |
【三 初赛二进制】
32位整数 补码:
00000000 00000000 00000000 00000101 这是5
00000000 00000000 00000000 00000000 这是0
11111111 11111111 11111111 11111111 这是-1
11111111 11111111 11111111 11111110 这是-2
11111111 11111111 11111111 11111101 这是-3
11111111 11111111 11111111 11111100 这是-4
11111111 11111111 11111111 11111011 这是-5
11111111 11111111 11111111 11111010 这是5取反的结果-6
所以计算机对整数的运算用的是补码(别再忘了QAQ
即正数原反补不变 ; 负数对我们所熟知的原码 除符号位外 取反+1:
-1的原码 10000001
-1的补码 11111111
-1的反码 11111110
所以举例:树状数组中 6&-6 就是 -6取反=11…11001 再+1 11…11010 则00…0110&11…1010 就是6的最小非0位(lowbit)
【2020.2.23更新】
https://www.cnblogs.com/zsq1993/p/5792065.html
关于 *和const 优先级等的细节
1 { 2 const int a; 等价于 int const a; 3 short int a; 等价于 int short a; 4 } 5 6 { 7 int x,y; 8 //[]优先于* 9 10 int *a[10]; //可理解为 int* a[10] 11 a[0]=&x; 12 13 int (*b)[10]; //b指针 用来指向 int[10],但是初始b没有被定义指向 14 int c[5][10]; 15 b=&(c[1]); 16 (*b)[4]=1; 17 printf("%d ",c[1][4]); 18 } 19 20 { 21 int x,y,z,w; 22 const int *a; 23 int const *b; //a和b是一样的 24 int *const c=&z; //指针常量 必须得赋初值 25 26 a=&x; 27 x=1; //可以 28 //*a=1; 不可以 29 30 b=&y; 31 y=2; //可以 32 //*b=2; 不可以 33 34 z=3; //c指针是只读,但指向位置的值没关系 35 *c=3; //可以 36 37 int const *const d=&w; //将前两者结合 38 w=2; 39 }