當你在信息學競賽\((OI)\)中進入了提高組時,你可能會被卡常!
卡常!
程序被卡常數,一般指程序雖然漸進復雜度可以接受,但是由於實現/算法本身的時間常數因子較大,使得無法在OI/ICPC等算法競賽規定的時限內運行結束。
常數被稱為計算機算法競賽之中最神奇的一類數字,主要特點集中於令人捉摸不透,有時候會讓水平很高的選手迷之超時或者超空間。
——來自某度百科……
快速讀入
簡稱快讀,是信息學競賽中卡常數最為常見的方法。
一般來講,大多數題目的出題人都不會到這種喪心病狂的地步。
不過,以防萬一肯定沒壞處啊~ 反正代碼很簡單啦
代碼
先上代碼!講解在后面。
inline int read(){
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
} // 這是能判負數的C++快讀模板
在代碼中,只需將cin >> n
或scanf("%d", &n)
改成n = read()
即可!
原理分析
為什么\(cin\)慢?因為它需要和\(stdio\)保持同步,也就是sync_with_stdio
。
為什么\(scanf\)慢?原因有點復雜。
- 它可以接受多種形式的輸入(數字、字符串等等),因此需要判斷。
- 它因為某些安全原因——輸入太快可能會有些玄學的\(bug\),具體的我也不太清楚。
其實在\(C++\)中,依次讀入單個字符是比一次讀入一個數要快的,因此我們可以用\(getchar()\)來負責讀入。
在實際的文件中,會有許多不必要的隱藏字符,比如換行符\n
等。
因此,我們需要先排除掉這些字符,也就是第一個\(while\)循環。但是有一個特例:\(-21904\)中的\(-\)號。這個負號不是數字啊!於是我們用\(w\)當數的符號。有負號時,\(w\)從原來的\(1\)轉化成了\(-1\)。
於是,我們要特判!if(ch == ‘-’) w = -1;
這就是判負號的語句。
下一個循環中,就是位值原理。數\(\overline{abcd} = 10 \times (10 \times (10 \times a + b) + c) + d\),讀者自證不難。
最后返回\(n = sgn(n) \times |n|\),其中\(sgn(x)\)為\(x\)的符號。