C++:竞争性编程技巧的解释

C++: Explanation for a Competitive Programming Tip

本文关键字:解释 编程技巧 竞争性 C++      更新时间:2023-10-16

在用于竞争性编程的DMOJ在线判断中,如果问题只需要读取无符号整数数据类型,则加快执行时间(C++(的技巧之一是在顶部添加此宏。

这是如何工作的?使用它的优点和缺点是什么?

#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x= (x<<3)+(x<<1)+_-'0');}while(0)
char _;

来源:https://dmoj.ca/tips/#cpp-io

首先让我们重新格式化一下:

#define scan(dest) 
do { 
while((dest = getchar()) < '0'); 
for(dest -= '0'; '0' <= (temp = getchar()); dest = (dest<<3) + (dest<<1) + temp - '0');
} while(0)
char temp;

首先,外部do{...}while(0)只是为了确保正确解析宏。请参阅此处了解更多信息。

接下来,while((dest = getchar()) < '0');-这可能只是dest = getchar(),但它通过丢弃'0'字符下面(但不是上面(的任何字符来做一些额外的工作。这可能很有用,因为空白字符都"小于"ascii中的0字符。

宏的核心是for循环。首先,初始化表达式dest -= '0'利用ascii编码中0-9字符相邻且连续的事实,将dest设置为由字符表示的实际整数值。因此,如果第一个字符是'5'(值53(,则减去'0'(值48(得到整数值5

条件语句'0' <= (temp = getchar())做了几件事——首先,它获取下一个字符并将其分配给temp,然后检查它是否大于或等于'0'字符(因此在空白处会失败(。

只要字符是数字(或至少等于'0'(,就计算增量表达式。dest = (dest<<3) + (dest<<1) + temp - '0'-temp - '0'表达式从ascii到数值进行了与以前相同的调整,移位和加法只是乘以10的一种模糊方式。换句话说,它相当于temp -= '0'; dest = dest * 10 + temp;。乘以10并加上下一个数字的值就是最终值。

最后,char temp;声明临时字符存储,以便在程序中的后续宏调用中使用。

至于你为什么要使用它,我怀疑与scanfatoi相比,它是否能提供任何可衡量的好处。

它所做的是通过一系列过早的优化逐个字符地读取数字。有关更多详细信息,请参阅@MooseBoys的回答。

关于它的优点和缺点,我认为使用它没有任何好处。类似于x * 10(x<<3)+(x<<1)之类的优化应该由编译器而不是您来完成。

据我所知,cincout对于所有竞争性编程目的来说都足够快,尤其是在禁用与stdio同步的情况下。自从我开始竞争性编程以来,我一直在使用它,从未遇到过任何问题。

此外,我自己的测试表明,尽管人们普遍认为cincout并不比C I/O慢。你可以试着自己测试它的性能。请确保已启用优化。

显然,一些有竞争力的程序员过于关注快速I/O之类的东西,而他们的算法才是最重要的。