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;}//代替取模-
或者對於模數p進行#define宏定義
絕對值優化:
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的莫隊快的飛起,模擬退火燒到了你上輩子的屁股;