NO.10: 迴圈展開:
在快取和暫存器允許的情況下一條語句內大量的展開運算會刺激 CPU 併發(蛤?這是個什麼原理,算了,反正寫了沒壞處就這麼寫吧)
NO.9: 特殊運算優化:(或許這真的沒用)
取模優化:
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;}//代替取模-
絕對值優化:
inline int Abs(int a){//絕對值優化
{ int b=a>>31; return (a+b)^b; }
NO.8: 前置++/--運算子:(有利無弊)
NO.7: if()else語句比()?():()語句慢(但慢的不多,在判斷較少的時候還是用if吧)。
網上很多說if比?:慢,但是其實不是這樣的。二者的彙編除了檔名不一樣其他都一模一樣。其實不是?:比if快而是?:比if-else快。
NO.6: 內聯:
函式內聯:比如說:
inline add(int u,int v) { star[++cnt].to=v; star[cnt].nxt=head[u]; head[u]=cnt; }
但要拒絕inline大遞迴函式,用的少的函式比如只用1次的就不要inline了,那樣反而更慢;
另類內聯:
struct haha{ int v,x; inline bool operator < (haha tar){//強制內聯 return v<tar.v; } }lala[MAXN+1];
NO.5:使用區域性變數的效率比使用靜態變數要高。
因為區域性變數是存在於堆疊中的,對其空間的分配僅僅是修改一次\(esp\)暫存器的內容即可.而區域性變數存在於堆疊中最大的好處是,函式能重複使用記憶體,當一個函式呼叫完畢時,退出程式堆疊,記憶體空間被回收,當新的函式被呼叫時,區域性變數又可以重新使用相同的地址。當一塊資料被反覆讀寫,其資料會留在\(CPU\)的一級快取(\(Cache\))中,訪問速度非常快。而靜態變數卻不存在於堆疊中。
NO.4:優化STL
大部分的STL較慢的原因是在動態記憶體分配時對push_back()的函式大大的不友好;
我們可以手寫足夠大小的記憶體池來代替動態分配記憶體。
#include<bits/stdc++.h> using namespace std; #define reg register static char space[10000000],*sp=space; template<typename T> struct myalloc:allocator<T>{ myalloc(){} template<typename T2> myalloc(const myalloc<T2> &a){} template<typename T2> myalloc<T>& operator=(const myalloc<T2> &a){return *this;} template<typename T2> struct rebind{typedef myalloc<T2> other;}; inline T* allocate(size_t n){ T *result=(T*)sp;sp+=n*sizeof(T); return result; } inline void deallocate(T* p,size_t n){} };
list<int,myalloc<int> > L;vector<double,myalloc<double> > vec //容量的定義
但當記憶體過大時,不要套用此程式碼,因為該程式碼為了簡短並沒有釋放記憶體;
NO.3: I/O優化
scanf比cin快得多,printf比cout快得多,如果你不知道就……就現在知道了
普通版:(適用於正負int範圍內的數)
void read(int &x) { int f=1;x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} x*=f; }
提升版:(快是快,但在考試中的價效比並不高)
inline char get_char(){//超級快讀 static char buf[1000001],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } 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; }
NO.2: register
在定義一個變數時加一個register,其意義是將該變數放入暫存器中進行運算(如果可以的話),
它的效果在該變數不斷重複使用時間的優化極大,往往用時是不優化的40%;
NO.1: #pragma GCC optimize(2)(請勿在NOIP中作死)
這便是O2優化
它的作用極大,但如果程式碼不規範,它在優化時會改變某句程式碼的含義,所以在用時一定要小心從30%TLE變為100%WA;
實踐證明開了O2的莫隊快的飛起,模擬退火燒到了你上輩子的屁股;