OI中卡常數技巧


一、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語句比()?():()語句要慢,逗號運算符比分號運算符要快。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM