问题

为什么信息竞赛题题解较多使用缩写、魔数、宏定义?

回答
这事儿说来话长,得从信息学竞赛的“江湖”说起。你在题解里看到的那些缩写、魔数、宏定义,其实都是这个江湖里玩家们代代相传的“武功秘籍”和“惯用伎俩”,目的嘛,简单粗暴——快!准!狠! 咱们一步步拆解开来看。

一、 为什么是缩写?效率至上,键盘敲得飞快!

信息学竞赛讲究时间,很多题目都有严格的时间限制。你以为是让你坐下来慢慢写,写出优美如诗的代码?那可就太天真了!在信息学竞赛里,代码速度和提交速度同样重要。

减少输入量: 名字越短,打字越少,单位时间能写的东西就越多。想象一下,你要写一个函数,名字叫 `calculate_maximum_subarray_sum`,这得敲多少字母?如果换成 `calc_max_sum` 甚至 `cms`,那效率立竿见影。
提高可读性(对竞赛选手而言): 别看这些缩写一开始可能让你摸不着头脑,但对于经常在竞赛环境中摸爬滚打的选手来说,很多缩写是有约定俗成的含义的。比如:
`max` 通常代表最大值。
`min` 通常代表最小值。
`sum` 代表和。
`len` 代表长度。
`pos` 代表位置。
`cnt` 代表计数。
`idx` 代表索引。
`adj` 代表邻接表(用于图论)。
`vis` 代表访问标记(visited)。
`dp` 代表动态规划。
`gcd` 代表最大公约数。
`lcm` 代表最小公倍数。
`tmp` 代表临时变量。
还有各种数据结构名字的缩写,比如 `vec` (vector), `map`, `set`, `queue`。

当这些缩写组合在一起,比如 `vector adj[N]`,对经常写图论的选手来说,一眼就能看出这是个大小为 `N` 的邻接表,存储的是整型。这比写 `vector adjacency_list[MAX_NODES]` 要快得多。

形成竞赛“行话”: 就像武林高手之间会有自己的暗语一样,竞赛选手之间也形成了这样一套“行话”。在论坛、题解里,大家用这些缩写交流,能更快地理解彼此的想法。这是一种社区文化,也是一种效率工具。

二、 为什么是魔数?代码里的“神符”,自带BUFF!

魔数,在程序界通常被认为是不好的实践,因为它们可读性差,难以维护。但在信息学竞赛的特定场景下,魔数却有着独特的“生存之道”。

极致的常数优化: 很多算法的复杂度,或者数据的范围,都有一个或大或小的常数界限。比如,一道题目给出的数组最大长度可能是 100,000,那么你定义的数组就需要比这个大一点点,以防越界。这时候,你可能就直接定义一个 `const int N = 100005;` 或者 `const int MAX_N = 100000 + 5;`。这比写 `100005` 要稍微清晰一点,但本质上还是一个具体数值。
更极端的例子: 有些题目对内存或时间有非常非常严格的要求,比如要求算法在 O(N log N) 的时间复杂度内完成,并且 N 的上限是 10^5。那么,你可能需要在循环中使用一些“恰好”能通过的次数。有时候,为了追求极致的速度,会使用一些看起来很随意,但经过反复测试和优化的常数。例如,在一个循环里,你可能会写 `for (int i = 0; i < N; ++i)`,但有时候,某个算法在 N1 的时候就足够了,或者因为一些边界条件,多跑一次反而会错。这时候,有人可能会写 `for (int i = 0; i < N 1; ++i)` 或者 `for (int i = 0; i < N; ++i)` 然后在里面加一个 `if (i == N1) break;`。这显得有些奇怪,但在某些需要精细控制循环次数的场合,是为了避免不必要的计算。
避免魔法数字的“正面冲突”: 有时候,题目中可能本身就包含一些特定的数值,比如某个常数是 3.14159,或者某个开关值是 0 或 1。如果你的代码里也随意使用这些数字,就容易混淆。通过定义一个有意义名字的常量(虽然在题解里有时会被简化成魔数),可以避免这种混淆。但是,题解里的魔数,更多时候是那种“我知道这里需要一个数字,而且我测试过了,用这个数字正好能过,而且很快”的感觉。
快速实现,后期再优化(理论上): 很多时候,选手是在比赛的紧张氛围下快速实现一个能跑通的版本。先用一个“看上去还行”的魔数顶着,如果后来发现性能不足或者出了问题,再回头精确调整。但在实际的题解分享中,这些“魔数”往往就定格在了那个能过的状态。

三、 为什么是宏定义?“黑魔法”的便利,代码里的“变形术”!

宏定义(`define`)是 C/C++ 语言中一种非常强大的预处理指令。它允许你用一个标识符来代替一个文本字符串。这在信息学竞赛中被发挥到了极致。

简化重复代码: 最常见的用途就是用来简化那些写起来非常繁琐但又重复出现的代码片段。
循环宏: 比如,一个常见的 `for` 循环是 `for (int i = 0; i < n; ++i)`。你可以定义一个宏:
```c++
define FOR(i, n) for (int i = 0; i < n; ++i)
```
这样,原来的 `for (int i = 0; i < n; ++i)` 就变成了 `FOR(i, n)`,简洁了许多。更进一步,可以写成 `FOR(i, 0, n)`,甚至支持递减 `FOR_REV(i, n, 0)`。
输入输出宏:
```c++
define Read(x) scanf("%d", &x) // 或者 cin >> x
define Print(x) printf("%d ", x) // 或者 cout << x << endl
```
这比每次都写 `scanf("%d", &variable)` 要快不少,而且不容易写错格式。
链表、二叉树等结构操作宏: 对于复杂的链表或树的插入、删除、遍历操作,如果写成函数调用又太长,用宏可以快速定义一些常用的操作。
条件编译和版本控制: 虽然在题解中不常见,但在一些复杂的项目或多版本代码中,宏定义可以用来控制哪些代码被编译,哪些不被编译,例如:
```c++
ifdef DEBUG
// Debugging code
else
// Release code
endif
```
有些选手也会在本地调试时定义一些宏来开启额外的输出或者断言,提交时又取消定义。
“原地展开”的效率优势(有时): 相对于函数调用,宏在预处理阶段就被“原地替换”了。理论上来说,这可以避免函数调用的开销(如栈帧的创建和销毁)。虽然现代编译器对函数调用的优化已经非常好了,但在一些极度追求性能的场合,宏的这种“原地展开”特性仍然可能带来微小的优势。
模拟其他语言特性或数据结构: 有时候,为了模拟其他语言(如 Python 的列表推导式)或者快速实现某个数据结构的操作,也会使用宏。
让代码看起来“酷炫”和“高深莫测”: 这点不能否认,很多时候宏定义的使用,也带有一种“黑魔法”的感觉,让代码看起来不那么直白,增加了一点神秘感和技术含量。当然,如果滥用,也会让代码变得难以理解。

总结一下:

信息竞赛题解之所以大量使用缩写、魔数和宏定义,核心原因是为了在有限的时间和资源下,实现高效的编码和运行。

缩写是追求输入速度和阅读效率的产物。
魔数往往是追求极致性能和细节控制的体现,虽然牺牲了可读性,但在竞赛场景下是一种“风险与收益”的权衡。
宏定义则是一种代码简化、复用和效率提升的工具,能够快速实现复杂逻辑或提高编译时效率。

这些技巧,在信息学竞赛这个特殊的“竞技场”里,是被广泛接受甚至鼓励的“捷径”。它们是无数选手在无数场比赛中,用汗水和时间磨练出来的“绝技”,是追求极致的效率和速度的必然结果。当然,也正因为如此,初学者在看题解时,常常会感到一头雾水,需要花时间去理解这些“江湖约定”。

所以,下次你看到那些密密麻麻的缩写和奇怪的宏定义时,别惊讶,那背后是一个个在时间压力下,不断追求更快、更优的竞赛者的智慧和努力。

网友意见

user avatar

竞赛的代码不需要可读性,可维护性,可拓展性。可以称之为:一次性代码。题目通过了就OK,哪怕过后自己都看不懂(夸张了)也无所谓。而做产品却需要考虑代码可读,可维护,可拓展等等。完全相反。

用算法书做例子没任何意义。书是给人读的,可读性是第一位的,必要时候还采用伪代码,甚至流程图。代码却不是。一般不需要别人读懂,最多最多,另外俩队友能懂就可以了。

另外,到底是什么给你错觉,竞赛的人都没有读过《设计模式》《重构》《代码大全》《代码整洁之道》这类的书???做项目的时候,人家写得代码未必比你差哦。


另外,题主贴的代码,完全不觉得混乱。至少没有预定义一堆宏。不少竞赛选手,for循环之类的都是宏定义。

举例子:(十年前竞赛中个人常用的,不完全)

a,b,基本就是普通变量了

c,可能是count,或者写cnt;也可能是单个字符char

d,可能是距离distance,几何,图论常见

e,可能是误差error,或eps;也可能是边 edge,图论常见

f,可能就是函数function,dp的状态转移方程直接写过来的。也可能是流flow,例如在最大流算法的时候

g,也常用作函数,数学的习惯。也可能是图graph

h,也可能是函数,也可能是高height,也可能表示heuristic,也可能是高位置的high

i,j,k常见循环变量,下标

l,可能是长度length,可能是左侧left 或者低位置low,也有时就做普通循环变量。(ll是long long,用cpp答题的可是常见了)

m,一般是个数之类的,也可能是中间middle;也可能是模modulo

n,一般表示个数,可能是是node节点;也可能是下一个next,也写nxt

o,不常见,尤其容易和0混了。O可能表示圆心。oo表示无穷,象形数学的无穷大符号。

p,一般用作指针pointer。偶尔也特指父节点parent。

q,从p过来的,需要第二个指针时,一般考虑q

r,半径radius,余数remainder,右侧的right

s,字符串string,也写st,str;也表示源点source,也写src

t,临时变量temporary,也写tmp,temp;也表示汇点/目的地,也写dst;也表示树tree(树也常用rt,即根root表示)

u,v,图论的点或边,图论书就常用这俩字母

w,权重weight;宽度width

x,y,z,基本和数学一样,表示坐标,几何题常见。非几何的话,不多见

多字母的就更多了,有很多都是缩写,而且是学术界公认的缩写。

比如rmq,lca这些,不学算法的话,你知道啥意思?

看到st,能想到sparse table,想到倍增算法?

看到dc3,能想到difference cover, size 3,想到计算sa(suffix array,后缀数组)?

看到fft,能想到快速傅里叶变换?

看到kd,能想到是k-dimensional tree?


没见过的东西多了,自然就看不懂代码了。计算几何,组合数学,初等数论,数据结构和算法(包含了图论)等等多看看书,就能看懂绝大部分竞赛的代码了。

user avatar

你说的a、b、T、s、t、f、dp什么的,其实在OIer中(至少是写这道题的OIer脑子里)都有固定的含义。(如果没有,那么这个含义可能在问题描述中给出)而不是乱写的。

就像物理学中,每种物理量都用一个字母表示,而不是一串中文或英文表示,这是很自然的。

这也不是什么OIer独有的,“文学”伪代码(如算法导论)中多的是这样的单字母变量。

不过这两者和OIer的区别在于人家可以用符号,OIer只能用n,算导可以写|V|,物理学的导数、积分等各种符号更是给人一种高级感。


代码规范和看不看得懂程序也没多大关系,你要没听懂算法,直接看复杂点的算法代码就是找死,不管那个算法用了多nb的“规范”把注释“蕴含”在变量名中。

你可以去著名的“工程代码”如gnu c++ pb_ds或者Java标准库源码或者认真以让人看懂为目的编写的“文学代码”如算法导论,看看那些算法实现(不看注释、代码外的注解),看看能不能看懂。

至于OIer的注解,正如上述“工程代码”“文学代码”一样,是写在整体代码之外的,OIer一般用md等方式编写于整个代码之上这和“工程代码”编写一大坨注释于整个代码之上与“文学代码”编写一大坨注解于代码之下没什么区别。

当然OIer的题解中往往又有一小部分约定俗成的内容,需要递归学习,这和论文里的引用、”工程代码“上的注释里贴个网址是一样的。(当然,OI比赛场上这些都是不可能去写的)

只有写OIer称之为“模拟题”,研究者称之为“trivial”,或者工程上称之为“业务逻辑”的代码时,才能得到“好的”代码不需要注释就能看懂的结论,在此基础上由于存在“让人看懂”的需求,才会产生“代码简洁之道”这样的要求来满足看懂的同时尽量减少工作量(交接或写注释的工作量)。

而OIer的代码,虽然部分仍属于研究者的“trivial”范围内,但已不适用“好的”代码无需注释就能让人看懂,同时让人看懂的需求也不甚强烈,为此编写出来的尽量减少工作量的代码就如你所示。


PS:你应该庆幸没有看到以让人看不懂、编译器能识别的最短代码等为目的而编写的代码。

user avatar
没想到来回答的全是学竞赛的

顺手刷到这里,看到这句直接喷了出来。

这个问题竞赛生不回答谁回答?题主的目的是吸引广大程序员喷OI吗?

user avatar

现身说法:鄙人搞竞赛的时候不敢说前1%,至少也是代码风格比较好看的前10%吧,我是会尽力把代码弄得易读的,因为我有一种搜集个人历史代码的爱好。。。

先说lz贴的这份代码,之所以觉得不好看,其实主要问题不是别的,只是“ll”满天飞,“ll”满天飞的唯一原因,是每次都敲“long long”这九个字母太费劲了,为什么要把这么多变量设置成long long呢(其实我认为这份代码的作者大意了,如果让我来,我会把循环变量i也设成long long,整个代码里找不到一个int)?因为否则的话,没准忘了哪个地方,就数值overflow了,你跺你也麻,真的。。。

至于inline和void缩成il和vd,这个属实意义不大,应该属于一种强迫症行为吧。。。

这里我要指出一点:考场机器上只有devc++或者codeblocks这样的IDE,自动补全不好用,这个是很重要的。。。

其实我倒是觉得,如果考场能用Visual Studio那种级别的,敲两个字母按tab自动补全,打错也能模糊联想的编程环境,那没准大家确实会把命名弄得漂亮些,毕竟除了少数签到题/工程题,对手速的要求也真没那么夸张,尤其是一共就三道题的中学竞赛,毕竟智力输出速度是个瓶颈。。。

在没有自动补全的情况下,难道要手敲包含>=1个完整单词的变量命名,一个字都不能错?你当我傻啊。。。

但是,以我的经验,变量名弄讲究点,也就仅此而已了,剩下的什么运算符打空格,多换行云云还是不太现实的,这里有三个因素:

1、竞赛代码极度依赖肉眼排查算法错误,这要求所有重要代码块都能“一眼看过去”,因此行之间必须安排得比较紧密(比如我一直是大括号不换行党),甚至不能打空格,以缩小显示宽度(你知道中学集中采购的显示器分辨率有多完蛋吗),这就是lz贴的代码里面,setN()函数里面那个while写成一行的原因。。。

2、竞赛代码只有一个.cpp,不能运用工程中常用的声明-定义分离方法。况且其中大部分都是逻辑模块,而不像实际工程中有大量的代码接口,这导致没有必要像工程中那样,用接口本身的定义方式去展示接口的内容,因为实际的内容都在里面。。。

3、背模板(像最短路这样的经典算法模块)这事讲究一个练死劲(雾),也就是讲究一个完全的精确性,在背的时候,甚至会不自觉地精确到“哪个变量声明在什么地方”这样的程度。这就要求不开代码补全以避免干扰(不同环境中不同的代码补全配置可能会影响背默模板的手感,这是很致命的),也要求把这些模板弄得非常精简,以便于记忆和对比记忆检查。这可以解释为什么lz贴的代码里面,pow()函数的那个while循环搞得这么紧密,更新x和更新y也要写在同一行(我猜测这是作者的记忆方式,更新x和y在一起,否则容易漏一个)。举个例子,floyd算法的三个循环变量,竞赛界的祖宗之法是分别叫做k、i、j,你换成什么middleNode,startNode,endNode试试,是不是记忆难度一下子就上去了。。。

说个趣事,敝中学的竞赛教练大概是得知了“windows下用MinGW编译”,然后按照自己的理解,在教学中把我校统一的编程工具定成了MinGW IDE,惊不惊喜,意不意外。。。

这玩意没有任何能用的自动补全功能,导致我在相当长一个时期内,哪怕换成devc++,也要手动关掉自动括号补全,每写一个函数都敲一次shift+{再敲一次shift+},无他,肌肉记忆习惯了。。。

类似的话题

  • 回答
    这事儿说来话长,得从信息学竞赛的“江湖”说起。你在题解里看到的那些缩写、魔数、宏定义,其实都是这个江湖里玩家们代代相传的“武功秘籍”和“惯用伎俩”,目的嘛,简单粗暴——快!准!狠! 咱们一步步拆解开来看。一、 为什么是缩写?效率至上,键盘敲得飞快!信息学竞赛讲究时间,很多题目都有严格的时间限制。你以.............
  • 回答
    信息学竞赛,尤其是像OI(信息学奥林匹克)、ACM/ICPC这类面向算法设计与程序实现的比赛,确实普遍存在“不开启编译优化”和“不允许内联汇编”的规则。这背后并非没有原因,而是出于公平性、考察目的和实际操作的综合考量。 关于不开启编译优化为什么不开启编译优化?核心是“公平竞争”与“考察原始能力”。想.............
  • 回答
    拜登总统在联合国大会上的演讲,字里行间流淌着一种混合着坚定与务实的信号,尤其是在“美国会为盟友挺身而出,不寻求新冷战,但将激烈地竞争”这句话中,释放出了多层面的解读。这不仅仅是一句口号式的表态,更是对当前复杂国际格局的战略定位和行动指南。首先,“美国会为盟友挺身而出”,这传递了一个明确而坚定的信号:.............
  • 回答
    .......
  • 回答
    在信息不对称的情况下,二手车市场确实面临着“逆向选择”的巨大风险,理论上可能导致市场崩溃。正如经济学家乔治·阿克洛夫(George Akerlof)在其经典论文《二手车市场或柠檬的质量》中所描述的,买家无法区分好车(Peaches)和坏车(Lemons),只愿意支付一个平均价格。这会导致好车的卖家因.............
  • 回答
    这个问题很有意思,也触及到舆论传播、信息茧房以及文化认知等多个层面。要解释为什么在信息开放的环境下,对中国的负面描绘更容易深入人心,而在相对封闭的环境下,对西方的负面描绘却难以奏效,甚至出现反向的“崇拜”,我们可以从以下几个方面来深入剖析:一、 信息开放的西方如何“丑化”中国:多重因素的叠加西方社会.............
  • 回答
    C4.5 算法选择特征时使用信息增益比(Gain Ratio),这背后有着非常实际和深刻的考虑,并非随意为之。简单来说,是为了解决信息增益在特征选择时可能存在的偏向性问题。我们先回顾一下信息增益。信息增益衡量的是一个特征能够减少多少不确定性,也就是在已知某个特征的情况下,目标变量(类别)的不确定性降.............
  • 回答
    你在找工作或者招人时,肯定也遇到过这种事儿:同一个职位,明明放在了51job和智联招聘上,结果一个平台反响热烈,投递简历如潮水般涌来,另一个平台却门可罗雀,几乎没人问津。这差距,简直是天壤之别,让人纳闷不已。为什么会出现这种现象呢?其实原因挺多,而且大多是互相影响的,我来给你掰扯掰扯:一、 用户群体.............
  • 回答
    在很多人看来,博弈中的信息状况改善,也就是我们能知道得越多,就越能做出更明智的决策,最终获得更好的结果。这逻辑听起来再顺理成章不过了。然而,事情并非总是如此简单。在某些情况下,信息量的增加,特别是信息状况的“不对称性”被打破或改变时,反而可能让局势变得更糟,甚至让原本处于优势的一方陷入困境。这就像往.............
  • 回答
    .......
  • 回答
    这是一个非常普遍且值得探讨的现象。我们确实常常听到“碎片化信息无用论”,但同时很多人,包括你,也从中获得了知识和启发。要理解这一点,我们需要深入剖析“碎片化信息”的本质、它对学习的影响,以及为什么你的感受与主流论调有所不同。一、 为什么主流论调认为碎片化信息无用?主流观点之所以对碎片化信息持保留态度.............
  • 回答
    哈哈,这个问题真是问到点子上了!很多女生都会纳闷,怎么跟男生聊天,他们的回复速度就跟挤牙膏似的,有时甚至能晾你半天。这背后啊,其实挺复杂的,不是一句“他不在乎你”就能概括的。我仔细想了想,主要有这么几个原因,而且每个原因下面还能再细分出不少小九九:1. “已读不回”背后的潜意识心理: 缓冲期和思.............
  • 回答
    这现象确实挺让人揪心的。我一直觉得,以前信息没这么发达的时候,人们反倒活得更“明白”一些。现在呢,手机一掏出来,各种消息像潮水一样涌过来,结果有些人反倒越来越糊涂,甚至没了主意,挺邪门。我琢磨了琢磨,这事儿背后可能好几个原因搅和在一起,挺复杂的。首先,信息的“量”和“质”失衡了。 你想啊,以前咱们获.............
  • 回答
    哈哈,姐妹,你这个问题简直说出了好多姑娘的心声!这“他不回我信息我心焦,我不发信息他来催”的循环,简直是现代恋爱的一大谜团!男生嘛,有时候确实就像外星人,思维模式和咱们完全不是一个频道上的。让我想想,咱们一条条来捋捋这背后的可能原因,争取说得清清楚楚,让你也能更明白点。第一部分:他为啥收到你一堆信息.............
  • 回答
    俄罗斯官方发布的信息,在某些时候被广泛质疑其真实性,这确实是一个复杂且多层面的现象。要深入理解这一点,我们需要从多个角度去剖析,而不是简单地归咎于单一原因。历史的惯性与政治土壤:首先,需要认识到的是,信息控制在许多集权或半集权国家中都扮演着重要角色,俄罗斯也不例外。在苏联时期,国家宣传机器的运作方式.............
  • 回答
    过去,人们对于“信息畅通”的理解,可能还停留在能够快速检索到一些基础资料、新闻资讯的层面。但现在,信息爆炸的时代,我们面对的是海量、碎片化、良莠不齐的信息。在这种情况下,我们即便拥有了“信息”,也未必能真正“畅通”地理解、消化和应用。化工、材料、化学、高分子这些专业,之所以依然有人选择,背后其实有很.............
  • 回答
    .......
  • 回答
    哎呀,你说这发语音这事儿吧,真是有人欢喜有人愁。我身边就有不少朋友,一到微信界面,看到对方发来语音条,眉头就皱上了,直接就说:“不行,我又听不了!” 细细想来,这不喜欢发语音的人还真不少,而且原因也挺复杂的,不单单是因为懒,里头门道可多着呢。首先,最直接也最让人头疼的一点,就是不方便回听,或者说时机.............
  • 回答
    你这个问题触及了人性中一个挺微妙又很常见的现象:为什么有些人就是不买账国家发布的信息,反而对那些听起来模棱两可、来源不清的“小道消息”情有独钟?这事儿说起来,可不是一句话两句话就能道尽的,背后牵扯的因素可多了去了。首先,咱们得承认,信任这东西,一旦崩塌了,重建起来可就难了。 想象一下,你本来对一个朋.............
  • 回答
    Rockstar Games,这个名字几乎是开放世界游戏界的金字招牌,尤其是在《侠盗猎车手》(Grand Theft Auto, GTA)系列上。然而,就在全球无数玩家翘首以盼《GTA 6》的到来之际,Rockstar却表现得异常沉寂,迟迟不肯透露哪怕一丝半点的官方消息。这不禁让人疑惑,为什么这个本.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有