程式玄學常數優化
阿新 • • 發佈:2018-12-23
一、讀入優化
讀入時的速度cin<scanf<getchar
我們可以用getchar()讀入整數
inline int read(){ int num=0; char c; while(isspace(c=get_char())); while(num=num*10+c-48,isdigit(c=get_char())); return num; }
fread是直接對二進位制檔案進行讀入,速度更快
const int MAXBUF = 100000; char buf[MAXBUF], *ps = buf, *pe = buf+1; inline void rnext() { if(++ps == pe) pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; if(ps == pe) return false;//EOF do{ rnext(); if('-' == *ps) f = -1; }while(!isdigit(*ps) && ps != pe); if(ps == pe) return false;//EOF do { ans = ans*10+*ps-48; rnext(); }while(isdigit(*ps) && ps != pe); ans *= f; return true; }
二、運算優化
1、位運算優化:乘上2的冪或除以2的冪時可以直接用位運算進行優化
2、除法、取模優化:除法運算的耗時是乘法運算的幾倍,能不用盡量不用,比如i/a>b可以以換成i>a*b
3、浮點數除法優化:
float a,b,c; init(a,b,c); a/=c; b/=c;
可以換成
float a,b,c; init(a,b,c); float d=1/c; a*=d; c*=d;
三、針對cpu快取的優化
1、一維陣列的陣列大小盡量開成2的冪,高維陣列每一維的陣列大小最好都不要開成2的冪!(狀壓dp時要尤其注意)
2、遍歷陣列時最好按陣列存放順序遍歷
For example
//first
for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j]*=2;
//second
for(int i=0;i<m;i++) for(int j=0;j<n;j++) a[j][i]*=2;
第一種比第二種效率快得多
3、陣列的索引也是需要時間的,特別是高位陣列的索引尋地址效率很低,因此我們可以用指標來代替陣列定址
//first int a[55][65][75][85]; int main() { int *p=&a[0][0][0][0]; for(int i1=0;i1<55;i1++) for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) (*(p++))++; } //second int a[55][65][75][85]; int main() { for(int i1=0;i1<55;i1++) { int (*p)[65][75][85]=a[i1]; for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) p[i2][i3][i4]++; } } //third int a[55][65][75][85]; int main() { for(int i1=0;i1<55;i1++) for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) a[i1][i2][i3][i4]++ }
很明顯,效率上第一種>第二種>第三種,但很多時候並不是單純的按順序訪問陣列,這種時候第二種寫法(只需要對3維陣列定址)就派上用場了