快速读入详解

当你在信息学竞赛((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 >> nscanf("%d", &n)改成n = read()即可!

原理分析

为什么(cin)慢?因为它需要和(stdio)保持同步,也就是sync_with_stdio

为什么(scanf)慢?原因有点复杂。

  1. 它可以接受多种形式的输入(数字、字符串等等),因此需要判断。
  2. 它因为某些安全原因——输入太快可能会有些玄学的(bug),具体的我也不太清楚。

其实在(C++)中,依次读入单个字符是比一次读入一个数要快的,因此我们可以用(getchar())来负责读入。

在实际的文件中,会有许多不必要的隐藏字符,比如换行符 等。

因此,我们需要先排除掉这些字符,也就是第一个(while)循环。但是有一个特例:(-21904)中的(-)号。这个负号不是数字啊!于是我们用(w)当数的符号。有负号时,(w)从原来的(1)转化成了(-1)

于是,我们要特判!if(ch == ‘-’) w = -1;这就是判负号的语句。

下一个循环中,就是位值原理。数(overline{abcd} = 10 imes (10 imes (10 imes a + b) + c) + d),读者自证不难。

最后返回(n = sgn(n) imes |n|),其中(sgn(x))(x)的符号。

原文地址:https://www.cnblogs.com/newbiePWang/p/10192655.html