一、I/O優化
讀入優化是卡常數最重要的一條!
1 inline int read() 2 { 3 int x=0,f=1;char c=getchar(); 4 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 5 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 6 return x*f; 7 }
輸出優化好像不常用...
二、inline
在聲明函數之前寫上inline,可以加快一下函數調用,但只能用於一些操作簡單、調用頻繁的函數。涉及遞歸,大號的循環等很復雜的函數,編譯器會自動忽略inline。(我不知道強制inline有沒有用)。
三、register
在定義變量前寫上register,用於把變量放到CPU寄存器中,適用於一些使用頻繁的變量(比如循環變量),但寄存器空間有限,如果放得變量太多,多余變量就會被放到一般內存中
快到什么境界?
register int a=0; for(register int i=1;i<=999999999;i++) a++; int b=0; for(int i=1;i<=999999999;i++) b++;
優化:0.2826 sec
不優化:1.944sec
四、初始化優化
在初始化Floyd或者其他類似的東西
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) gra[i][j]=inf for(int i=1;i<=b;i++) gra[i][i]=0
是比
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==j) gra[i][j]=0; else gra[i][j]=inf }
快的(測試大約1是2的80%的時間)
原因后者每次都要判斷
五、循環展開
循環展開也許只是表面,在緩存和寄存器允許的情況下一條語句內大量的展開運算會刺激 CPU 並發(前提是你的 CPU 不是某 CPU)...
- 減少了不直接有助於程序結果的操作的數量,例如循環索引計算和分支條件。
- 提供了一些方法,可以進一步變化代碼,減少整個計算中關鍵路徑上的操作數量。
用法(下面是一個將一個int 類型數組初始化為0的代碼段):
void Init_Array(int *dest, int n) { int i; for(i = 0; i < n; i++) dest[i] = 0; }
而如果用循環展開的話,代碼如下:
void Init_Array(int *dest, int n) { int i; int limit = n - 3; for(i = 0; i < limit; i+= 4)//每次迭代處理4個元素 { dest[i] = 0; dest[i + 1] = 0; dest[i + 2] = 0; dest[i + 3] = 0; } for(; i < n; i++)//將剩余未處理的元素再依次初始化 dest[i] = 0; }
六、取模優化
//設模數為 mod inline int inc(int x,int v,int mod){x+=v;return x>=mod?x-mod:x;}//代替取模+ inline int dec(int x,int v,int mod){x-=v;return x<0?x+mod:x;}//代替取模-
七、前置++
后置 ++ 需要保存臨時變量以返回之前的值,在 STL 中非常慢。事實上,int 的后置 ++ 在實測中也比前置 ++ 慢 0.5 倍左右(UOJ 上自定義測試)
八、bool優化
不要開bool,所有bool改成char,int是最快的(原因不明)。
九、選擇結構優化
if()else語句比()?():()語句要慢,逗號運算符比分號運算符要快。