目录
快读快写
首先,快读快写代码是什么?
以下是模板,解释以注释的形式给出了
如果你对getchar不熟悉,可以先看下面的小tips。
typedef long long ll;
inline ll read(){ //内联函数
ll n=0;
int f=1;
char c=getchar(); //获取字符赋值给c
while(c<'0' || c>'9'){ //一直不断的判断,直到读到数字,如果读到符号,f=-1,记录一下
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){ //读数字,最后用户或者我们输入完之后会有回车,回车也读,以此出循环
n=(n<<3)+(n<<1)+(c^48);//移位运算符,在下面细讲
c=getchar();
}
return n*f;//返回
}
左移运算符
假设int n=1;
二进制表示就是00000000 00000000 00000000 00000001 =1
左移3位
就是 00000000 00000000 00000000 00001000 =8
再左移3位
就是 00000000 00000000 00000000 01000000 =64
而从1开始左移一位就是
00000000 00000000 00000000 00000001=1
00000000 00000000 00000000 00000010=2 一位
00000000 00000000 00000000 00000100=4 两位
看出来了吗,一个相当于乘8,一个相当于乘2,加起来就是乘10。
哎呦呵,原来你就是乘个10啊,写这么复杂干什么,哎嘿,这么做肯定有道理
充满的你应该知道了,没错,就是快。
那么这个(c^48)这样写,是不是写成
(c - '0')啊
没错,就是可以这么做。
我们知道,
字符 '1' 到 '9' 的ASCII码值分别是 49 到 57。^表示按位异或操作符。
48的二进制表示是0011 0000
而57的二进制表示0011 1001
异或就是相同为0不同为1
自己推一推就知道啦——
哈哈,快之前,我们再说说快写
模板
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar((x%10)^48);
return;
}
先把负号打出来,通过递归致使到个位数,然后输出
这个(x%10)^48就等价于x%10+'0',一般用后者即可
那我们就很好理解了x%10得到的数一定是个位数
再异或48,相当于在48的基础上加这个个位数,因为putchar要输出字符嘛——
其次,为什么快,与谁比?
肯定与要样子的scanf和printf比或者cincout相比要快很多
我认为啊,首先读入字符打印字符嘛,肯定快,不向数字。其次,我的目的很明确,就做这些。
具体原因如下
减少函数调用:在快读和快写技巧中,通常会减少函数调用的次数。函数调用涉及到压栈、出栈等操作,会引入额外的开销。通过减少函数调用次数,可以降低开销,提高程序的执行效率。
减少格式转换:在快读和快写技巧中,尽可能减少了不必要的格式转换。例如,直接使用
%d
或%lld
等格式化符号读取整数,而不需要额外的类型转换。避免不必要的格式转换可以节省时间,从而提高程序的速度。缓冲区优化:快读和快写技巧通常会对输入输出的缓冲区进行优化。例如,使用
fgets
函数可以一次性读取一行数据,避免多次读取造成的开销。底层优化:在一些情况下,快读和快写技巧可能会涉及到底层的输入输出操作,绕过了标准库函数的一些封装,从而减少了不必要的中间环节,提高了数据的读写速度。
最后,什么时候都适用吗?
数据量大时,非常好用,虽然我还没用过,不过快了——哈哈哈
数据量小时,不建议用,没必要,当然可能会有不必要的麻烦
整数多,非常好;空格多,难搞;有浮点数,不搞。
网上还有其他类型的模板,用想用的就好,没太多区别。
只是有些更快一点,但都很快了,嘶,快~
OK,结束,祝您常AC~
小tips
如果对getchar不熟悉,可以看看这篇文章
下面是getchar的简单过程
在Linux中,getchar() 函数涉及以下主要步骤:
标准输入流的文件描述符获取:
在Linux中,所有的输入输出设备都被抽象为文件,包括标准输入、标准输出和标准错误输出。标准输入的文件描述符是 0。当程序调用 getchar() 函数时,它实际上是从文件描述符为 0 的文件(标准输入流)中读取一个字符。
等待输入:
当调用 getchar() 函数时,程序会进入一个阻塞状态,直到用户输入一个字符并按下回车键。这是因为 getchar() 函数会等待用户输入完成后才会继续执行程序。
字符读取:
一旦用户输入完成,操作系统会将输入的字符存储在输入缓冲区中。getchar() 函数通过系统调用读取输入缓冲区中的字符。
缓冲区管理:
输入缓冲区是一个临时存储区域,操作系统将用户输入的字符存储在其中,直到应用程序读取它们。getchar() 函数实际上是从输入缓冲区中读取一个字符并将其从缓冲区中移除。
字符转换与返回:
读取到的字符被转换成对应的整数(ASCII码值),然后作为 getchar() 函数的返回值返回给调用它的程序。如果读取失败或遇到文件结束符(EOF),则返回特殊值 EOF。
整个过程中,C语言标准库中的 getchar() 函数充当了一个高级接口的角色,隐藏了底层系统调用的复杂性,使得程序员可以方便地从标准输入流中获取字符,而无需直接与底层的文件描述符和缓冲区交互。