日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OI常用的常数优化小技巧

發(fā)布時(shí)間:2025/4/9 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OI常用的常数优化小技巧 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  注意:本文所介紹的優(yōu)化并不是算法上的優(yōu)化,那個(gè)就非常復(fù)雜了,不同題目有不同的優(yōu)化。筆者要說的只是一些實(shí)用的常數(shù)優(yōu)化小技巧,很簡單,雖然效果可能不那么明顯,但在對(duì)時(shí)間復(fù)雜度要求十分苛刻的時(shí)候,這些小的優(yōu)化對(duì)于幫助你成功卡常也是十分重要的。那么我們讓進(jìn)入正題吧。

  (1)inline放在自定義函數(shù)定義前

   不要問為什么,加就行了!額,這個(gè)東西就是內(nèi)聯(lián)函數(shù),好像可以讓你的函數(shù)有機(jī)會(huì)被計(jì)算機(jī)執(zhí)行得稍微快一點(diǎn),一般放在使用次數(shù)比較多的小函數(shù)前,像二分會(huì)常用到的check(),為sort()定制的CMP()等等,但是遞歸函數(shù)和較大的函數(shù)編譯器會(huì)自動(dòng)忽略,當(dāng)然主函數(shù)前就更不要放了。。。比如下面這個(gè)例子可以用: 

inline bool CMP(const int &a,const int &b){   return a>b;
}

  (2)register放在變量定義前

     這個(gè)可以有機(jī)會(huì)把變量申請(qǐng)存儲(chǔ)在CPU寄存器中成為寄存器變量然后跑得飛起但是CPU寄存器的內(nèi)存是很小的,因此一般只用來定義賦值次數(shù)較多的單個(gè)變量(比如,循環(huán)變? ? ? ? ? ? ?量),而且似乎是不能定義成為全局變量的。

  (3)++i比i++快

     記住就行了,盡量用++i而不用i++,當(dāng)然有特殊需要用i++時(shí)除外。

  (4)讀入優(yōu)化(很重要!)

  這是針對(duì)整數(shù)的。先介紹一下原理:讀入一個(gè)數(shù)時(shí)把它當(dāng)作字符讀比當(dāng)作一個(gè)數(shù)讀快,或者說用getchar(),gets()一類讀比用scanf("%d",&x)要快。而讀入字符時(shí)本身就是這樣讀的,當(dāng)然就不用優(yōu)化了。不要問為什么快!一般會(huì)自定義一個(gè)read()函數(shù)來讀取,寫法有很多,先貼上最常見的寫法:

inline int read() { int f=1,x=0; //f表示符號(hào),1為正,-1為負(fù)char ss=getchar(); while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}//跳過數(shù)字前的空格等字符while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}//讀到下一位ss,就把已讀到的乘10,相當(dāng)于全部進(jìn)一位,
                                  //為存ss留出空間
return f*x;
}
//使用時(shí)直接x=read(),相當(dāng)于scanf("%d",&x);

   然而裝逼是沒有止境的,你也可以這樣寫:

inline int read() { int X=0,w=0; char ch=0;//這個(gè)ch一定要賦初值,除了‘0’~‘9’(注意這里是字符)什么都可以,不然可能會(huì)出鍋的。。。 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; }

  ?首先問題是isdight()是什么玩意兒?它是定義在cctype頭文件中的一個(gè)函數(shù),用于判斷是否是整數(shù)。w|=ch=='-',其實(shí)相當(dāng)于w=w|(ch=='-'),|(或)是C語言中的一個(gè)位運(yùn)算符,如果a和b中有一個(gè)為1,結(jié)果就為1。w一開始等于0,而當(dāng)ch=='-'成立時(shí),表達(dá)式的值為1,0的二進(jìn)制|1的二進(jìn)制結(jié)果就是1,w就被賦值為1了,表示有負(fù)號(hào)。(X<<3)+(X<<1)=X*8+X*2=X*10,原因見后面。^(異或)也是位運(yùn)算符,筆者沒有仔細(xì)研究,不過可以肯定的是一個(gè)char型數(shù)字^48(0的ASCLL值)就等于它的int型數(shù)字,所以有(ch^48)一用法。要注意的是位運(yùn)算符比加減乘除的優(yōu)先級(jí)都要低,所以一定要加括號(hào)。

? ? ? 使用讀入優(yōu)化在數(shù)據(jù)規(guī)模較小時(shí)優(yōu)勢(shì)并不明顯,但在數(shù)據(jù)規(guī)模很大,比如上百十萬時(shí),使用讀入優(yōu)化會(huì)比不使用的讀取速度快上幾倍,為你成功卡常&暴力騙分爭(zhēng)取寶貴的時(shí)間。

? ? ? 事實(shí)上還有一種比讀優(yōu)都要快10%的讀優(yōu),就是用fread(),但是一般情況下不至于這么苛刻吧,所以筆者就不多說了(其實(shí)是筆者不會(huì))

  (5)輸出優(yōu)化

  既然有讀入優(yōu)化,自然也有輸出優(yōu)化。只是輸出優(yōu)化應(yīng)用機(jī)會(huì)很少(一般只輸出幾個(gè)數(shù)),只有在需要輸出的答案較多時(shí)才可能會(huì)用到。原理同讀入優(yōu)化,把原本為整數(shù)的答案轉(zhuǎn)為字符(串)形式后輸出。例如輸出一個(gè)int型變量x,一般會(huì)寫:

printf("%d",x);

    ? 而用輸出優(yōu)化就是:

inline void print(int x) { if(x<0){putchar('-');x=-x;} if(x>9) print(x/10); putchar(x%10+'0'); }

(ps:由于筆者的粗心,輸出優(yōu)化代碼前面打錯(cuò)了,特此更正)

  (6)使用位運(yùn)算符<<與>>

  這兩個(gè)東西是C語言中的位運(yùn)算符,什么意思呢?不會(huì)的可以百度一下,簡單來說就是一個(gè)數(shù)在二進(jìn)制狀態(tài)下向左(右)移幾位(超出的位數(shù)舍棄)后的值。比如1<<2,意思是把1的二進(jìn)制左移2位后得到的值。我們知道1的二進(jìn)制是1(2),左移2位,就是100(2),也就是4。那么8>>1的值是多少呢?8=1000(2),右移一位就是100(2),也就是4。也許你會(huì)驚奇地發(fā)現(xiàn)a<<b就等于a*2^b,a>>b就等于a/2^b。沒錯(cuò)!這就是我們要用到它的地方。當(dāng)你寫a=a/2時(shí),你也可以寫成a=a>>1;a=a*2也可以寫成a=a<<1,等等。    

   那么,為什么我們非要用這個(gè)位運(yùn)算符呢?因?yàn)樵贑語言中,位運(yùn)算比起加減乘除等屬于較底層的操作,加減乘除其實(shí)也是通過位運(yùn)算實(shí)現(xiàn)的,算是一種把底層操作更高級(jí)地“打包”起來,就像高級(jí)語言是由機(jī)器語言轉(zhuǎn)化而來的,執(zhí)行時(shí)仍然要編譯為機(jī)器語言,這中間當(dāng)然會(huì)花費(fèi)一些不必要的時(shí)間和空間,因此越底層的操作往往越快。并且,我們可以用1<<n很方便地表示2^n,在實(shí)際操作中很有用處。

-->最后,筆者還想提醒一點(diǎn),據(jù)學(xué)長所說inline和register是兩個(gè)非常玄學(xué)的東西,有時(shí)可能還會(huì)造成負(fù)優(yōu)化。。。(好了我就是想說被卡了別找我)

?

  初次發(fā)表博文,希望能幫到大家,請(qǐng)多多指教.

2018-08-15

轉(zhuǎn)載于:https://www.cnblogs.com/gosick/p/9484087.html

總結(jié)

以上是生活随笔為你收集整理的OI常用的常数优化小技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。