眾所周知,OI中其實就是算法競賽,所以時間復雜度非常重要,一個是否優秀的算法或許就決定了人生,而在大多數情況下,我們想出的算法或許並不那么盡如人意,所以這時候就需要一中神奇的的東西,就是底層優化;
其實底層優化比較簡單,比如我們經常使用的 register還有快讀,這些都可以進行優化。還有fread,但是fread在一些情況(尤其是在重要的的比賽時)但是還是給出下面的優化
const int L=1<<20|1; char buffer[L],*S,*T; #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) #define debug(x) cerr<<(x)<<" x"<<endl; #define re register inline LL read() { re LL a=1,b=0;char t; do{t=getchar();if(t=='-')a=-1;}while(t>'9'||t<'0'); do{b=b*10-'0'+t;t=getchar();}while(t>='0'&&t<='9'); return a*b; }
還有的話就是一些位運算優化來卡常:那么我們經常使用的運算其實是非常慢的,他的時鍾周期如下:
那么我們就可以想象到平時我們寫程序的時候其實是常數巨大的
優化就是自己打函數,不調用庫函數,由於stl的封裝,導致調用函數的時候都是很慢的
介紹一下inline函數,這個可以讓函數強制在線,其實可以把他當成當你使用它的時候,他可以將你寫的函數相當於復制粘貼一般的直接插入代碼,減少了部分訪問函數的時間;
但是這並不是所謂的強制的,他只是建議在線,並且遞歸函數不能調用,其實編譯器並不會報錯,因為加了inline編譯器也不會在線,因為編譯器無法預測遞歸的層數;
這個其實是減少浮點除法的優化方法;
由於他麻煩,所以筆者在考試和刷題過程中並沒有使用過,感興趣的神犇可以嘗試一下,我先說好,如果沒有十足的把握,不要在考試的時候使用,一切后果自負;
我在網上看見了神犇的重新定義了log函數,據說比調用stl中的函數快了1.4倍,但是蒟蒻表示看不懂,據說這是指令集的匯編語言(本蒟蒻瞎比比的)
其實重載一些運算其實真的挺有用的,他可能有時候真的可以卡常,還有這個關於指令集,之前學長來給我們講課的時候說過一句,說是wc2015(好像是)里面介紹了指令集n方過百萬的方法;
但是筆者還未達到那種水平,所以在這里就不做介紹了,至於他的可使用性,經過學長的證實,他確實使用指令集n方過了十萬,其實已經非常強了
這是一些常用的位運算來優化常數(其實在平時並用不大,或許只有喪心病狂的人才痴迷於這個)
然后其實就沒有什么了,還有就是可以將循環展開,因為從一個循環跳轉到下一個循環的時候會調用很多時鍾周期,這樣很耗時,循環展開很好使,但是循環展開代碼復雜度很大,稍有不慎就會車毀人亡;
這是常用的函數重載
位運算優化
這里我就想說一點,筆者其實並不喜歡關於卡常這方面的東西,但是筆者身邊總有一些人不再算法上改正,光企圖使用卡常的手段通過一些數據很水的題,其結果並沒有達到訓練的目的,而且我很欣賞一句話: 在實現之前的任何優化都是罪惡之源
所以這篇博客只是希望我和大家可以學到一些技巧,並不希望大家和我痴迷於此;
endl;