1
2012年10月,江城市的天气一夜入秋。
实验初中初一的课业比小学重了不少,但陈远却把所有的课余时间,都砸在了那台大脑袋显示器和父亲给的那本《高级语言程序设计》上。
六年级时看爸爸编程,他觉得写小游戏好玩;但到了初一,当他正式接触到NOIP(全国青少年信息学奥林匹克联赛)的题库时,他才发现,代码的世界后面,藏着一个与奥数类似、浩瀚与残酷的竞赛赛道。
这一年的全国初赛,陈远过得有些惊险。靠着扎实的奥数底子,他硬生生背下了那些生涩的计算机基础知识,踩着分数线,勉强拿到了十月份复赛的入场券。
复赛那天,江城市第一中学的考场外挤满了人。
“小远,别有压力。”
爸爸陈知行今天穿着一件洗得干干净净的藏青色工装夹克,兜里照旧揣着他下车间用的游标卡尺,温和地拍了拍陈远的肩膀,“这是你第一次参加正规联赛,就当是去见识见识世面。记住,稳住你的数理逻辑,账就不会太乱。”
“知道了,爸。”陈远嚼着薄荷糖,单肩拉着书包带子,深吸了一口气往考场里走。
在进实验楼大门的时候,陈远因为避让旁边成群结队的一中选手,不小心撞到了花坛边上的一个男生。
“不好意思啊。”陈远下意识道歉。
那个男生转过头,推了推黑框眼镜。他穿着一件明显洗得有些褪色、甚至袖口有些脱线的旧校服,脚下的运动鞋边沿还开了一块小胶,手里正抓着一个两块钱的豆沙面包,啃得满嘴都是碎屑。他长得太普通了,在周围那些穿着光鲜、满嘴都是“名师押题”的一中尖子生里,他就像个来走场凑数的。
男生摇了摇头表示没事,把最后一口面包塞进嘴里,拍了拍手上的碎屑,把准考证往怀里一揣,低着头默默地走进了考场。
陈远瞥到了那张准考证上的名字——林子苏。
那时候陈远还不知道,这个看起来甚至有些寒酸、毫无竞赛生锐气的男生,就是少年宫传说中江城初中部唯一的“信息学神童”。
2
市一中的微机房里,一排排纯黑色的全液晶显示器散发着冰冷的光。
“啪嗒、啪嗒……”
下午两点整,当全省评测服务器轰然解锁,整个机房里瞬间被暴雨般的键盘敲击声淹没。
陈远坐在后排,手心微微有些冒汗。前两道基础模拟题他过得很快,这两年在电脑前敲代码的底子,让他对基本语法和简单的贪心模拟信手拈来,短短一个小时,他就把前两题的代码全部提交锁死。
然而,当第三题那道需要极高计算量的数论路径优化刷出来时,陈远被死死地卡住了。
这道题的数据规模极大,不仅要求在极短的时间内找出动态最优解,更对内存空间有着极其苛刻的限制。陈远在完全没有专业竞赛教练指导、全靠野生自学的情况下,凭借着恐怖的数理直觉,硬生生在纸上推导出了一个十分惊艳的递推式。
“本地静态样例全部通过!”
当他把这段核心代码敲进编译器,按下运行,看着控制台黑框里吐出和题目完全一致的正确答案时,陈远长长地舒了一口气。
他靠在转椅上,看着自己屏幕上那份清爽、毫无报错的代码,信心满满地按下了最终的提交键。那时候的陈远,心里甚至产生了一丝野生少年的骄傲:那些正规军有教练又怎么样?我自己摸索出来的方程,一样跑得非常完美。
他觉得,数学对了,程序就一定对了。
3
考试结束的铃声响起,机房里顿时炸开了锅。
陈远单肩挎着书包,带着一丝初阵告捷的轻松走下实验楼的台阶。此时,一中的正规军们正围成一圈,几个带队的教练也凑在旁边,正情绪激动地对刚才的压轴题进行赛后复盘。
“第三题绝对是树形背包!我把最大状态都枚举进去了,本地大样例跑了0.8秒,稳稳的省一!”一个一中主力兴奋地大喊。
“对,我也推出了状态转移方程,这次出题组放水了,数据不难。”
周围的人群里充满了乐观的快活空气。陈远站在外围听着,嘴里嚼着薄荷糖,觉得自己的解法跟他们差不多,心里愈发踏实。
就在这时,那个穿着开胶运动鞋、旧校服的林子苏低着头从旁边经过。一个一中的主力一把拉住他:“林子苏,你第三题怎么写的?也是套那个树形背包模板吧?”
林子苏停下脚步,有些木讷地推了推黑框眼镜。面对大家的注视,他没有聊自己写了多少行代码,也没有聊自己的方程有多漂亮,只是用一种极其平静、甚至有些沙哑的声音说了一句话:
“第三题最大的坑不是算法,是数据范围。最后两组权值达到了 10^12,中间累加会爆 int。还有,如果数组直接开两倍防止越界,空间会卡死在 64MB 的红线上,Linux评测机绝对当场报内存错误崩溃(RE)。”
周围原本喧闹的空气,在这一瞬间,诡异地死寂了下去。
刚刚还在叫嚣“稳稳省一”的一中主力,脸色瞬间一片煞白。
林子苏没有看任何人的反应,他只是把空了的面包包装袋塞进垃圾桶,把单肩书包往背上一甩,低着头,孤身一人走下了台阶。
别人在讨论解法,他却在讨论风险。
站在人群最外围的陈远,在听完林子苏那句话的瞬间,整个人如遭雷击,硬生生定在了原地。
他的脸色在深秋的夕阳里瞬间变得惨白,耳朵里甚至出现了一阵尖锐的鸣音。
薄荷糖在嘴里化开,泛起一阵冰冷彻骨的苦涩。
林子苏说的每一个字,都精准地戳在了他的死穴上。他没开 long long,他所有的累加器用得全是标准的整型。而且,为了防止越界,他的数组大小卡得死死的,根本没有做任何类似于空间优化的滚动保存。
逻辑是对的,但在官方评测机那不带任何感情的极限大数据轰炸下,他的代码会在递推到中途时瞬间溢出变成负数,他的内存会当场崩溃!
那一刻,市一中台阶上的喧闹声仿佛彻底离他远去。陈远死死攥着书包带子,看着林子苏那个在落日拉得极长的、寂静的背影,第一次深刻地领教到了信息学竞赛赛道上,那由于经验不足带来的、近乎绝望的残忍现实。
4
半个月后,复赛放榜。
不出所料,陈远的第三题在跑过前三组小数据后,后面大数据的黑色屏幕上瞬间亮起了一片刺眼的红色——【WA(答案错误)/ RE(运行时错误)】。
总分两百多分,全省排名两百开外。
班主任递给陈远一张薄薄的、写着“普及组全省二等奖”的奖状,宽慰道:“陈远,初一第一次参赛就是省二,在我们学校已经是突破了!”
陈远接过奖状,指尖有些发颤。而红榜的最顶端,林子苏的名字以全省前十的绝对优势,冷冰冰地挂在省一等奖的序列里。正规军完备的工程训练和林子苏对边界的极致敏感,让他踩着 58MB 的内存极限,用最精妙的空间优化把所有工程隐患全部堵死了。
数学正确,不等于程序正确。信息学竞赛,从来不相信纸面上的完美。
那天晚上回到家,陈远拿出一本崭新的、厚重的硬皮本。借着书桌前那盏台灯的光,他提起笔,在第一页的最上方,一笔一划、极其利落地写下了一行大字:
《评测机不会替你补全边界》
在这行字的正下方,少年用最严厉的黑色笔迹,列出了一张冰冷的清单:
数据范围
数组越界
整型溢出
初始化
特殊情况