關於OI中簡單的常數優化

有些東西借鑑了這裏qwqgit

1.IO(istream/ostream) 輸入輸出優化程序員

以後能,在賽場上常見的幾種輸入輸出:算法

  輸入:緩存

  $1.cin$ 呵呵,不說什麼了,慢的要死。大概$1e8$個數要讀1分鐘左右數據結構

  $2.scanf, \_ \_ builtin \_ scanf()$ $scanf$ 其實還不算太快,可是$\_ \_ builtin \_ $在$NOIp$賽場上會$CE$ 函數

  $3.read()$ 美其名曰:讀入優化(反正本寶寶不會),在各大神犇的提交記錄以及題解上隨處可見,親測確實比$scanf$要快許多優化

  代碼大概長這樣: $by\ Young\ Neal$ui

int getint(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}

  $4. fread$ 歡迎來自$AK$爺的飛速文件讀入輸出spa

struct file_io{
    #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
    char inbuf[1 << 25], *pin, outbuf[1 << 25], *pout;
    int stk[20];

    file_io(): pout(outbuf) {fread(pin = inbuf, 1, 1 << 25, stdin);}
    ~file_io() {fwrite(outbuf, 1, pout - outbuf, stdout);}

    inline void getint(int &num){
        bool neg = 0; num = 0;
        while(!isdigit(*pin)) if(*pin++ == '-') neg = 1;
        while(isdigit(*pin)) num = num * 10 + *pin++ - '0';
        if(neg) num = -num;
    }

    inline void putint(int num){
        static int *v = stk;
        if(!num) *pout++ = '0';
        else{
            if(num < 0) *pout++ = '-', num = -num;
            for(; num; num /= 10) *v++ = num % 10;
            while(v != stk) *pout++ = *--v + '0';
        }
    }

    inline void nextline() {*pout++ = '\n';}
} fio;
#define getint(num) fio.getint(num)
#define putint(num) fio.putint(num)
#define nextline() fio.nextline()

  

  輸出:code

  $1.cout$ 呵呵,和$cin$一個樣

  $2.printf , \_ \_ builtin \_ printf$ 已經比上面那個快多了,可是同樣,$\_ \_ builtin \_ printf$會$CE$

  $3.puts("")$ 對於已知字符串來講,能用 $puts()$不用$printf()$ 可是$puts("")$輸出以後會換行

  $4.fio$見上面 (STO GhostCai)

固然了,在$NOIp$範疇內,輸入輸出量並不算太大,多數$printf(),scanf()$就能夠了,

除非$……$

你是要暴力碾標算而後再去$diss$一頓出題人數據水的神犇$……$

這時候讀優就必不可少了。

2.內存優化

  某$shadowice1984$大佬最擅長的東東,如下引用$shadowice1984$給本寶寶講課時候的話:

「咱們的$CPU$要對某一個數進行計算的時候,會先在一級緩存中找這個數的地址要是找到了,直接揪過來~~槍斃~~進行計算,速度很快的,

可是一級緩存能儲存的東西不多,就是幾個$int$,若是沒有找到,成爲'一級緩存未命中',可是,這時候,咱們還有一個二級緩存和三級緩存,一樣,也很很快,

而‘三級緩存未命中’以後,卻要去內存裏找這個東西了,這裏面會經歷虛擬地址與物理地址的互相轉換而後還有$……(\text{此處省略})$而後耗時巨大(相對於從緩存直接調用來說)。

這是後,咱們就會稱爲$cache\ miss$,而若是咱們的程序由於$cache\ miss$的次數太多而致使常數因子看似特別大(理論複雜度正確可是就是$tle$),就習慣的成爲卡$cache$」

  當本寶寶聽完這段話以後,

  

哇$……$真是一個暴力碾標算的好方法

那麼$……$咱們怎麼才能減小$cache\ miss$呢?

  $1.$保證內存的連續訪問

  這就是爲何本寶寶鄰接鏈表寫的每次都比別人慢上差很少一倍$qwq$ ,由於如今只有本寶寶用結構體寫了啊啊啊啊啊啊!

  $2.$多個$for$循環能夠適當調整順序

  最明顯的就是矩陣乘法和$Folyd$算法了,對於$folyd$ $(eg. \ NOIp2016 \text{換教室})$

for(int i=1;i<=n;i++)
  for(int j=1;j<i;j++)
    for(int k=1;k<=n;k++)
      d[i][j]= d[j][i]=min(d[i][j],d[i][k]+d[k][j]);

 

for(int k=1;k<=n;k++)
  for(int i=1;i<=n;i++)
    for(int j=1;j<i;j++)
      d[i][j]=d[j][i]=min(d[i][j],d[i][k]+d[k][j]);

  親測第二種寫法會比第一種寫法快好多呢。

  矩陣乘法同理,

for(int k=1;k<=n;k++)
  for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
      c.num[i][j]+=a.num[i][k]*b.num[k][j];

  把$k$這一維放到外面明顯比放到裏面要快

 

3.register 與 inline

  $register$在$for$裏面真的會快一點,用法就是$for(register int i=1;i<=n;i++)$

  $inline$ 只能用在沒有遞歸的函數裏,其實手動$inline$是個很好的東西,可是不必定。

  這兩個有的時候會形成負優化,這就呵呵了。

  

 

4.(僅限於$NOIp$等不開$O2$的賽事上) 手寫$stl$

  $stl(\  C++ \ Standard\ Template \ Library  \ )$  確實特別好用,也是$C++$的精華所在,

  能夠爲程序員們節省很大的時間,

  可是,在不開$O2$的狀況下,會由於種種緣由慢的要死,

  儘可能背過一些簡單的數據結構,能少用就少用。

 

5.玄學(信仰)優化:

(1). 打表優化

 若是有的寫的非正解,可是又想拿高分,全打表得話會超過代碼長度限制,這是後能夠部分打表,記得作過一道題

    對於30%的數據,知足n<=500;

    對於100%的數據,知足n<=1000;

  而後我和$shadowice1984$都會一個$On^{3}$的方法,顯然確定過不了$1000$

  以後,本寶寶放棄了,拿了$30$分去一邊哭去了,

  $shadowice1984$,$n^{3}$信仰過$500$,而後又信仰的打了一下$n=995$到$n=1000$的表

  而後就$……$ 而後就 $A$ 了

  

  數據範圍內,只打極限數據,放心,出題人必定會很毒瘤的

  還有優化打表的方法:查分優化,二次查分優化,$26$進制壓縮($eg.$樹的平均路長問題)

(2).女裝優化(親測有效)

  女裝能夠大大的減小$bug$和常數,真的親測有效,模擬賽的時候$t$的東西,**後再測就過了。。

(3).神犇優化(親身經歷) 

  有一次網上打$nowcoder$的比賽,而後和旁邊的神犇代碼比較一下只有變量名不一樣(纔不是互相抄的呢)

  而後$……$人家神犇就過了,本寶寶就$T$了,

  平時作題的時候,本寶寶常常出現用時和神犇差距很大,

  本身寫線段樹都已經不記錄$l,r$了,還比那些開結構體記錄$l,r$的神犇慢$……$ 

  真的是人菜常數大,真的是$……$

  ~~因此想暴力碾標算的話,先要成爲神犇~~

  

(4).信仰優化

  $srand(1926****)$ $srand(\text{cp或神犇生日})$

  $eg.\ srand(20020902) \ \ srand(20020224)  $

  (左cp右神犇)

  而後當你

 

printf("%s",rand()%2?"Yes":"No")

 

的時候會增大$AC$率的 ($NOIp2017\ \ D1\ \ T2$)


但願有用(光速逃~)

相關文章
相關標籤/搜索