1 条题解
-
0
自动搬运
来自洛谷,原作者为

KobeBeanBryantCox
请牢记:你曾在 OI 的星空中留下过属于自己的轨迹。搬运于
2025-08-24 23:01:33,当前版本为作者最后更新于2024-07-29 12:47:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P10815 【模板】快速读入 题解
题目好评!
这篇题解讲一下快读的原理,顺便讲一下快输的原理。
update on 2025-2-3:更新了原理,之前的原理是有问题的(感谢 @LionBlaze 大佬)。
update on 2025-6-28:被这个 Hack 了,真恶心,改了一下。
快读
我们都知道
getchar的速度快于普通的cin或者scanf(原因放在了最后),于是我们考虑能不能使用getchar读入字符代替数字。众所周知,每个可见字符都有其对应的 ASCII 码编号,那我们就考虑使用字符的编号与数字进行联系。
上面两句其实是废话。这显然可以做到。
于是我们就按照顺序读入数字。
我们应该先读入掉前面没用的字符,比如空格之类的。
同时应该注意如果读入减号,我们应该打一个标记表示这个数字是负数。
char c=getchar(); while(c<'0'||c>'9') // 非数字的过滤掉 { if(c=='-')f=-1; // 标记是负数 c=getchar(); }然后再读入数字,从高位到地位,每次读入一个个位数,我们应该把原来已经读入好的乘 再加上这个个位数。
举个例子,读入了 ,原来的是 ,我们要的效果是 ,那么我们先 ,再 。
这个应该都能理解吧,如果理解不了,可以想想小学做竖式计算的过程和这个有什么联系。
while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar(); // 注意是数字才读入,然后 c-'0' 的意思是找到 c 对应的个位数总快读代码:
int in() { int k=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; // 别忘记标记的负数要乘进去 } // 调用时用 n=in();
快输
由快读同理可得,我们能使用
putchar代替普通输出。由于按位输出,从高到低,不好操作,这里采用递归的形式。
不知道递归的读者出门右转,度娘在等您。
先处理负数。
if(x<0)putchar('-'),x=-x;然后分类讨论。
- 小于 ,代表是个位数,直接输出数字对应的字符:
if(x<10)putchar(x+'0');- 大于等于 ,这个时候应该先递归输出高位,再输出低位。
else out(x/10),putchar(x%10+'0');其中
x/10是去掉个位后的 ;x%10是取出 的个位。不懂的可以像我上面那样举例自己验证。总快输代码:
void out(int x) { if(x<0)putchar('-'),x=-x; if(x<10)putchar(x+'0'); else out(x/10),putchar(x%10+'0'); } // 直接调用 out(n) 就行了
本题 AC 代码
注意一下本题卡常,要用
getchar_unlocked,原理跟getchar差不多,只不过更快一点。不过不建议平时写题用这个,因为有些编译器会报错。
update on 2025-6-28:被卡
int了,全部改成long long就能过了。#include<bits/stdc++.h> #define Code using #define by namespace #define wjb std Code by wjb; // 至于这个是什么,咳咳,我不说 #define int long long int in() { int k=0,f=1; char c=getchar_unlocked(); while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar_unlocked(); } while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar_unlocked(); return k*f; } void out(int x) { if(x<0)putchar('-'),x=-x; if(x<10)putchar(x+'0'); else out(x/10),putchar(x%10+'0'); } signed main() { int n=in(),sum=0; while(n--)sum+=in(); out(sum); return 0; }
快读快输比正常输入输出快的原因
update on 2025-2-3:将此段不合理的表述删去,加入正确的内容。
cin和cout的特点- 同步流:
cin和cout与 C 语言的标准输入输出流(stdin和stdout)是同步的。这种同步机制保证了在混合使用 C++ 的cin/cout和 C 的scanf/printf时不会出现输入输出混乱的情况。但同步操作会带来额外的开销,因为每次进行输入输出操作时,都需要进行一些同步检查和处理,这会降低输入输出的效率。我们常说的关闭同步流就是在这里进行加速。 - 格式化处理:
cin和cout支持丰富的格式化输入输出功能,例如可以方便地处理不同类型的数据(如整数、浮点数、字符串等),并且可以通过setw、setprecision等操纵符进行格式化设置。然而,这些格式化处理需要进行复杂的类型检查和转换,会消耗较多的时间。(注:@LionBlaze 大佬说cout是调用了sprintf这个比较慢的函数,不过正确性未知。)
scanf和printf的特点- 格式化解析:
scanf和printf是 C 语言中的输入输出函数,它们也需要进行格式化解析。例如,scanf("%d", &num)需要解析格式字符串%d,并根据该格式从输入中读取相应的数据。这种格式化解析过程会带来一定的开销,尤其是在处理大量数据时,开销会更加明显。
不过上面这一段我觉得一点用都没有,快读快输比正常读入输入快这一条性质背下来就行了啊 QAQ。
后记
如果有什么写的不好或者错误的地方,欢迎评论指出!
- 1
信息
- ID
- 10595
- 时间
- 2500ms
- 内存
- 512MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者