C++细节一览

目录

1. 赋初始值

2. 变量类型

3. 子程序

4. 强制转换

5.运算上溢 取模运算

6.保留字

7.位运算

8.运算符

9.数组

10.脑残bug集锦

 

11.变量&数组&时间

12.C++编译器

1.    赋初始值

如果是上来就需要进行运算的变量,一定要先赋初始值再用!!!

(1)布尔型变量:默认初始值指不定是啥,有一回跑程序的时候发现居然既不是true也不是false,直接把while循环卡TLE了,直接爆零;

(2)整型变量:子函数中显然会随机分配一个初始值,主程序里默认是0,然而本机上跑是这样,其他地方就不一定了,保险起见该赋成啥赋成啥,以免正式比赛爆零哭死。。。

(3)数组:必要性和(2)一样。可以用memset函数,头文件<cstring>或<memory.h>。

  以下几种赋法仅限于memset使用,如果是单个变量会赋成其他值,如0x3f会赋成63!!!

① 赋0用memset(f,0,sizeof(0));

② 极大值的几种赋法:

0x3f:1061109567——10^9(int)

          4557430888798830399——4*10^18(long long)

0x7f:2139062143——10^9(int) 32位最大值,当心爆炸

          9187201950435737471——9*10^18(long long)

③ 极小值的赋法:

-128:-2139062144——10^9(int)

           -9187201950435737472——9*10^18(long long)

④ 布尔型:memset(f,true,sizeof(f))

2. 变量类型

(1)scanf和printf里int和long long不能混用。

假如设一个long long型变量n,读入的是scanf(“%d”,&n),结果保不定会给n赋成啥值,反正不是你想要的n。

懂?当你敲完代码却无论如何都调试不过时,瞅瞅是不是读入出了问题,也许会有惊喜呦~

(2)scanf和printf里float和double和long double不能混用。

xp表示乱搞得更厉害了……反正不管怎么赋,它都不会给你赋成原本的n……说起来scanf就是个大小姐,毫无回旋余地,而C++又是个不管事儿的,编译从来不报错……少年,还是静态查错吧……

正确类型:

int

%d

long long

%lld

float

%f

double

%lf

long double

%llf

K位小数 float

%.kf

还有,printf也是个蛇精病,long double会玩出神奇的花样。。。

所以浮点数还是多用cin和cout,以防爆炸。。。

 (3)函数中的参数类型

有的时候我们需要调用C++自带的数学函数库,那么应该怎样传入参数,跑出来的又是什么样的结果呢?

① log()

log()函数默认以e为底,也就是说实际上跑的是f(x)=ln x。然而大部分情况下我们用到的都是以2为底的log2x,那么用换底公式改一下就好log(x)/log(2)。

实际上log跑出来是啥关键跟运算结果有关,结果是整数,跑出来就是整数;结果是小数,就传出小数,精度跟传出变量类型有关。

② pow()

pow(a,b)——a的b次方。

虽然不知道咋跑的但似乎int和double都可以跑的样子。。。

3. 子程序

对于需要递归的过程,子程序是必须的,而且有时为了美观整洁,也需要把程序分块填装到子程序中在嵌到主程序里。有时不需要传入参数,但有时候还是有必要的,这时候就要注意变量类型的统一,整型和浮点数不能乱搞,int和long long、float和double最好也不要乱搞。。。中规中矩地该用啥用啥该是啥是啥最保险了。

4. 强制转换

很多时候当前已有的变量不能满足运算需要(精度啦上界啦内存啦。。。),需要进行转换。没啥好说的直接来就行。。。举例:n=(int)m,m=(double)(n)……但是有时还是要留心:m=(double)n1/(double)n2,这里分子分母都转化了才能用。

5. 运算上溢取模运算

很多题数据范围都很坑,为了防止运算上溢情况的发生,作为累加、累乘或者乘方结果的变量一般用long long比较保险。

有的题目明确指出要对p取模,那么跑程序分时候就不要犹豫,管他是加是减是乘是除还是乘方,运算一次取一次模,以防爆炸。

加:(a+b)%p=(a%p+b%p)%p

减:(a-b)%p=(a%p-b%p)%p;

乘:(a*b)%p=(a%p*b%p)%p;

除:(a/b)%p=(a%p*inv(b))%p=(a%p*pow(b,p-2)%p)%p

inv(b)表示b的逆元,b、p互质时可以用费马小定理求得inv(b)=bp-2

如果是连乘,一定要小心,根据数据范围判断一下,有时可能用交换律调整一下顺序就能避免乘积过大溢出的杯具。

6.保留字

C++ 74个保留字 不要拿来设变量。

count  find merge  size  ends end  等等,最好不要用,可以加个下划线啥的,或者缩成cnt、siz等等,尽量避开。

7.位运算

别和cin、cout混用,C++说<<、>>傻傻分不清楚。

>> 右移一位,相当于*2

<< 左移一位,相当于/2

8.运算符

<<和>>:参考楼上

=和==:前者赋值,后者判断(什么时候调试发现变量莫名其妙自己动了的时候,找if)

&和&&:前者按位与,后者and

|和||:前者按位或,后者or

9. 数组开太小

有时候打暴力或者测样例的时候会随手开个小数组(事实证明这个习惯简直糟糕透了),然后……交题的时候就忘了改了……一片RE……

C++数组从0开,习惯从1开始存的娃儿要注意开a[100000+1],保险起见最好再开大点。数组开大不要钱嘛!

10. 脑残问题集锦(仅针对本人)

①设好n不读入:读入时不结束(循环一直进行),或者只能读入一部分数据就卡住。

②int mian:嗯,手滑,手滑。。。

③for (itn i=1;i<=n;i++):嗯,再次手滑,手滑。。。

④文件名不合法:我犹记得第一回出这种bug时我还是个pascal菜鸟,一时兴起打了个程序“-w-”还是啥来着,然后……因为这个(2,+∞)的文件名被嘲笑了半个月……不过显然比赛中要关注的还是.cpp/.in/.out的文件名。对,一定要关联文件!!!!

 

⑤不输入using namespacestd;:一般会在cin、cout处报错

11. 变量&数组&时间

int 2147483647 (2^31-1)

long long 2^63-1

数组(int型,开long long型要除以2)

一维数组 3*10^7(33554432)

二维数组 5000^2左右(2.5*10^7)

三维数组 300^3左右(2.7*10^7)

四维数组 75^4左右(31640625,高度危险)

时间(均为不带常数状态下跑的)

O(n) 3*10^8——0.82s

O(n^2) 10^4

O(n^3) 700——0.92s(一般正解在200~300)

O(nlogn)

2^31——2s超时

1.6*10^7(2^24)—— 1s超时

1*10^7(2^23=8*10^6)——0.64s

综上,O(n)的10^8比较稳妥,O(n^2)跑10^4没问题,O(n^3)一般就在给200~300的数据时用,O(nlogn)一般在给的数据是2^x形式或一看就是二分时用

11.编译器

这个和操作系统有关,具体不好说,看各自电脑系统是32位还是64位,一般碰到这种情况先检查一下右上角好了

 

还有一个至今不明的错误(如果有大神知道原因希望可以不吝赐教),一般我个人的处理方法是Ctrl+A、Ctrl+C、Ctrl+N、Ctrl+V,再重存一个文件……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值