穿回初中的我,除了辣条什么都能优化
事情是这样的——
那天我加班到凌晨三点,正和一段祖传的“屎山代码”搏斗,突然眼前一黑,晕了过去。
再睁眼时,鼻腔里满是粉笔灰和劣质圆珠笔的味道。阳光被窗外的梧桐叶剪成碎片,洒在桌面上。黑板左上角写着 “等差数列求和” 六个大字,右下角则是一颗锃亮的地中海,在阳光里反射出近似 LED 指示灯的光泽。
“王老师……”我下意识嘟囔。
旁边一个瘦猴同桌用胳膊肘狠狠捅了我一下:
“别睡了!老王要提问了!你刚才都打呼了!”
我低头一看,自己穿着蓝白校服,桌上摊着七年级数学课本,扉页歪歪扭扭写着“初一(3)班 李码”。
完了,穿越了。
而且穿越的时机极其不巧——王老师正推着眼镜,目光像指针一样指向我。
“李码!你上来,把这道题演示一下。我看你刚才睡觉的样子,肯定在梦里把题都做完了吧!”
全班哄笑。 我踩着虚浮的脚步走上讲台,心里只有一个念头:撤回键在哪?Ctrl+Z!Ctrl+Z!
黑板上的题目,居然还很眼熟:
给你一个正整数 n,n不超过 1000 记: S奇 = 最小的 n 个正奇数的和 S偶 = 最小的 n 个正偶数的和
求 S奇 与 S偶 的最大公约数。
我心里一惊,这不是 LeetCode 3658 吗?一个程序员刷到这题,就像在新手村门口看到一只走地鸡。
我下意识想敲 import math,结果发现手里只有一支短得可怜的粉笔头;又习惯性想按 Tab 自动补全,结果只是两根手指在空中痉挛了两下——等等,我的 IDE 呢,我的 Copilot 呢?
同桌在下面小声嘀咕:“他在干嘛……搓大招吗?”
王老师皱眉:“李码,你手抽筋了?”
我回过神来,深吸一口气。 好吧,这破穿越系统连个新手礼包都不发,但至少我的大脑还装着九年义务教育加三年算法刷题攒下的内力。
我抓起粉笔,在黑板上端端正正地写:
第一步:求 S奇
最小的 n 个正奇数依次为:1,3,5,7,…,2n-1。 观察可知,这是一个等差数列,首项为 1,末项为 2n-1,项数为 n。 由等差数列求和公式,得: S奇 = (首项 + 末项)× 项数 ÷ 2 = (1 + 2n - 1) × n ÷ 2 = 2n × n ÷ 2 = n²
写完我手腕一抖,差点在后面戳了个分号——“Unnecessary semicolon” 我在心里默默 lint 了自己一把。
**第二步:求 S偶 **
最小的 n 个正偶数依次为:2,4,6,…,2n。 该数列为首项 2、末项 2n、项数 n 的等差数列。 同理,由求和公式得: S偶 = (2 + 2n) × n ÷ 2 = n(n+1)。
底下已经有同学开始倒吸凉气——毕竟初一生看字母运算,就像我第一次看没有类型注解的 Python 一样头皮发麻。
**第三步:求 GCD **
我把粉笔往黑板上一敲,职业病当场发作。
“好,现在问题变成了求 n² 和 n(n+1) 的最大公约数。如果暴力破解——先循环求和,再调用 gcd,复杂度 O(n),对于 n=1000 来说倒也够,但我们是工程师,要追求 O(1) 的极致优雅。”
王老师一脸懵:“欧……欧什么?”
我假装没听见,继续往下写:
由欧几里得算法可知:gcd(a, b) = gcd(a, b - a) 令 a = n²,b = n(n+1) = n² + n 则 gcd(n², n² + n) = gcd(n², n) 而 n 能整除 n²,故 gcd(n², n) = n
粉笔在 n 上狠狠画了个圈。
“答案是 n。不管 n 是 1 还是 1000,直接返回 n,别的啥也不用干。”
为了强化视觉效果,我还简单画了个流程图:开始 → 拿到 n → 直接输出 n → 结束
底下沉默了整整三秒,安静得能听见前排学霸同学转笔掉地上的声音。
王老师推了推眼镜,盯着黑板上的 gcd(n², n²+n) = n,突然问:
“你这‘欧几里得算法’……是哪本参考书上的?怎么我讲等差数列求和,你直接跳到数论了?”
我把粉笔头往盒子里一丢,拍了拍满手的白灰,下意识手插裤兜——没摸到手机,倒是掏出了两包辣条。 “王老师,这是一个程序员的基本素养。您想想——哪个硬核玩家打 BOSS 还一刀一刀平砍的?找机制漏洞,一招秒杀。”
同桌在后排张大了嘴:“李码,你是不是偷偷补课了……”
后来我确实因为“上课讲话太飘且公然携带零食”被罚站了十分钟。
我靠在走廊墙上,嘴里叼着根辣条,心情比连过三道 Hard 题还爽。窗外阳光正好,操场上有班级在跑圈,微风吹过来全是初夏的味道,混着粉笔灰和食堂中午的炸鸡排味儿——这配方,二十年后花多少钱都调不出来。
同桌趁老师写板书,从后门探出半个脑袋:“李码!你刚才说的那个欧欧欧到底是什么?你是在装逼还是真会啊?”
“欧几里得算法,求最大公约数用的,回头教你,包教包会。”
他眼睛一亮,然后又皱眉:“那你刚才在空中戳来戳去那个手势是啥意思?”
“那叫 Tab 自动补全,是一种……呃,失传的手艺。”
他似懂非懂地缩回去了。走廊那头,隔壁班的英语课代表抱着一摞作业本路过,她瞥了我一眼——大概是在想,这人怎么罚站罚得满脸笑嘻嘻的。
彩蛋:
这道题本质就是数学化简:
sumOdd= 1 + 3 + … + (2n-1) = n²sumEven= 2 + 4 + … + 2n = n(n+1)gcd(n², n(n+1))=gcd(n², n)= n
所以无论 n 多大(在题目的 1 ≤ n ≤ 1000 内),答案都是 n。 复杂度 O(1),额外空间 O(1)。
对应代码已经简单到了一种行为艺术的程度:
def gcdOfOddEvenSums(n: int) -> int:
return n
如果要整花活,也可以用 math.gcd 或手搓一个gcd 验证一下:
# from math import gcd
def gcd(a: int, b: int):
if b == 0:
return a
return gcd(b, a%b)
def gcdOfOddEvenSums(n: int) -> int:
sum_odd = n * n
sum_even = n * (n + 1)
return gcd(sum_odd, sum_even)

本作品采用
知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议
进行许可。