转载的其他大神的,感觉很受用.http://blog.csdn.net/leader_one/article/details/78430083
C++一些常数常见坑
I/O读入和输出
如果量小倒也没什么,如果大规模读入或者输出,C++自带的方式是很慢的
->首先,拒绝cin/cout,实在是太慢了,受不了
->接着scanf/printf,较慢,中小规模是可以的,但是百万级的I/O常数影响就大了
->所以考虑读入输出优化,百万级的I/O可以和scanf/printf相差0.X秒,和cin/cout则有几秒差距
以int类型为例
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
这是读入,利用getchar()来进行字符读入是比较快的
输出同理,putchar()
inline void write(ll x)
{
if(x==0){ putchar('0'),putchar('\n');return;}
if(x<0){ putchar('-'),x = -x; }
char s[22],l = 0;
while(x!=0) s[++l] = x%10+48,x /= 10;
fow(i,l,1) putchar(s[i]);
putchar('\n'); //这里输出换行了,可以改
}
寻址
由于没有开O2优化,会导致一些本来没有区别的变得比较明显。
多维数组把大的数放前面:
例如 int f[10000][1000][100] 而不是 f[100][1000][10000],跑起来差距0.Xs。
有时比算法的差距还大(开了O2后差别不明显)当然,比赛时一般没有O2,所以要注意–这是大坑
-
变量类型
例如 int和long long
int是4B的,32位,而long long是8B的,64位,所以在大规模运算时时间消耗上会有很大差别
能用小的就尽量别用大的
还有C++自带的string,常数实在是大,所以还是建议自己打char[ ]
-
C++自带STL
如果条件允许,最好还是自己手动实现,因为C++自带的STL常数很迷,有时可能大得惊人甚至导致TLE
所以,能自己手动实现最好还是自己写
当然,如果时间不允许或者不会写,用用也没关系
位运算优化
可以使用一些位运算来做一些运算的常数优化
例如:
x*10 => (x<<3)+(x<<1)
x!=y => x^y
x!=-1 => ~x
x*2 => x<<1 (其他2的幂数同理)
x*2+1 => x<<1|1
x/2 => x>>1
(x+1)%2 => x^1
x%2 => x&1
x%2==0 => ~(x&1)
函数/过程值得传递
例如 int calc(int a,int b)
如果只是传入一两个int、char什么的差距倒不明显,但如果是个string…显然就大了许多
可以使用全局变量或者&(直接用地址)来优化
循环内的问题
for(int i = 0; i <= n; i++)
{
work1();
work2();
}
for(int i = 0; i <= n; i++) work1();
for(int i = 0; i <= n; i++) work2();
运行效率哪一个快呢?
应该大多数人都觉得是第一种快,因为它少了一遍变量枚举-
其实这是片面的,如果work1( )和work2( )运算量都比较大的话,是第二种更快
这要由计算机的硬件说起。
由于CPU只能从内存在读取数据,而CPU的运算速度远远大于内存,所以为了提高程序的运行速度有效地利用CPU的能力,在内存与CPU之间有一个叫Cache的存储器,它的速度接近CPU。而Cache中的数据是从内存中加载而来的,这个过程需要访问内存,速度较慢。
这里先说说Cache的设计原理,就是时间局部性和空间局部性。时间局部性是指如果一个存储单元被访问,则可能该单元会很快被再次访问,这是因为程序存在着循环。空间局部性是指如果一个储存单元被访问,则该单元邻近的单元也可能很快被访问,这是因为程序中大部分指令是顺序存储、顺序执行的,数据也一般也是以向量、数组、树、表等形式簇聚在一起的。
看到这里你可能已经明白其中的原因了。如果work1和work2的代码量很大,例如都大于Cache的容量,则在代码1中,就不能充分利用Cache了,因为每循环一次,都要把Cache中的内容踢出,重新从内存中加载另一个函数的代码指令和数据,而代码2则更很好地利用了Cache,利用两个循环语句,每个循环所用到的数据几乎都已加载到Cache中,每次循环都可从Cache中读写数据,访问内存较少,速度较快,理论上来说只需要完全踢出work1的数据1次即可。
局部变量和全局变量
之前我也是一直觉得定义全局变量是要比定义局部变量要快的…
其实不然,还是要从硬件设计说起
因为局部变量是存在于堆栈中的,对其空间的分配仅仅是修改一次寄存器的内容即可(即使定义一组局部变量也是修改一次)。而局部变量存在于堆栈中最大的好处是,函数能重复使用内存,当一个函数调用完毕时,退出程序堆栈,内存空间被回收,当新的函数被调用时,局部变量又可以重新使用相同的地址。当一块数据被反复读写,其数据会留在CPU的一级缓存(Cache)中,访问速度非常快。而静态变量却不存在于堆栈中。
全局变量是用类似于递归调用的方式实现的,所以可处理的东西更多一点,时间换空间嘛。
当然,大变量(例如大数组)还是全局定义吧,局部绝对是会炸的。