C++:竞争性编程技巧的解释
C++: Explanation for a Competitive Programming Tip
在用于竞争性编程的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;
声明临时字符存储,以便在程序中的后续宏调用中使用。
至于你为什么要使用它,我怀疑与scanf
或atoi
相比,它是否能提供任何可衡量的好处。
它所做的是通过一系列过早的优化逐个字符地读取数字。有关更多详细信息,请参阅@MooseBoys的回答。
关于它的优点和缺点,我认为使用它没有任何好处。类似于x * 10
的(x<<3)+(x<<1)
之类的优化应该由编译器而不是您来完成。
据我所知,cin
和cout
对于所有竞争性编程目的来说都足够快,尤其是在禁用与stdio同步的情况下。自从我开始竞争性编程以来,我一直在使用它,从未遇到过任何问题。
此外,我自己的测试表明,尽管人们普遍认为cin
和cout
并不比C I/O慢。你可以试着自己测试它的性能。请确保已启用优化。
显然,一些有竞争力的程序员过于关注快速I/O之类的东西,而他们的算法才是最重要的。
- 在C++/Linux中设置单调时钟的一些技巧
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 请解释"函数1(p1,p2,p3);"的输出
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 被解释为低级别const的const对象的地址
- 计算每个节点的树高,帮助我解释这个代码解决方案
- MSVC将仅移动结构参数解释为指针
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 内联程序集printf将整数解释为地址
- 如何一步一步地正确解释此代码?(编程新手)
- C++:竞争性编程技巧的解释
- 我如何向只用Fortran 77编码的人解释面向对象编程?
- 有人能解释一下这些编程术语吗:引用语义,非线性可变状态
- 谁能解释一下我对欧拉 15 项目的动态编程方法有什么问题
- 你会如何解释一个外行人或编程初学者,面向对象方法的大胆点 - 安全
- 元编程技巧:如何简化两个元函数的实现
- 动态编程-最长的通用子字符串解释
- Windows程序员(C/C++)的Linux编程技巧
- 解释gcov输出以提高覆盖率的技巧是什么