Day 15 · 2026.07.07

离散数学

Discrete Mathematics — 计算机科学背后那门「数数与结构」的数学
"The infinite we shall do right away. The finite may take a little longer." — 归于 Stanislaw Ulam

数学归纳法

Mathematical Induction · 用两步证明无穷
Logic / Proof
直觉版

你面前排着无穷多张多米诺骨牌,想证明「它们全会倒」。你不可能一张张去推。归纳法说:你只需证明两件事——第一张会倒;以及「只要任意一张倒了,它一定会撞倒下一张」。这两件事一旦成立,无穷多张的命运就被锁死了。

归纳法的精妙,是把「验证无穷个命题」压缩成「验证一个起点 + 一条传递规则」。你从不真的走完无穷步——你只是证明了「这条链没有断点」。断不了的链,就是全倒的链。

P(0) 真 P(k) ⟹ P(k+1):每一张都撞倒下一张 …∞
正式定义
$$\big[P(0)\ \wedge\ \forall k\,(P(k)\Rightarrow P(k{+}1))\big]\ \Rightarrow\ \forall n\,P(n)$$

$P(n)$ 是关于自然数 $n$ 的命题。基础步 证 $P(0)$;归纳步 假设 $P(k)$ 成立(称 归纳假设),据此推出 $P(k{+}1)$。两步齐备,则 $P(n)$ 对所有 $n$ 成立。注意归纳假设不是「偷偷假设了要证的结论」——你假设的是「某一张倒」,要证的是「它撞倒下一张」,是传递而非结论。

为什么美

归纳法揭示了一件事:无穷不必用无穷的力气去对付。有限的两步论证,可以覆盖无穷个命题。更深的是,它不是一个「技巧」——皮亚诺公理里,归纳原理本身就是自然数的定义之一。换句话说,「自然数为什么能被归纳」不是一条定理,而是「我们把满足归纳的东西才叫自然数」。归纳法与自然数是同一件事的两面。它还有变体——强归纳(假设 $P(0),\dots,P(k)$ 全真)和 结构归纳(对树、表达式等递归结构施归纳),是同一精神的推广。

应用

归纳法是计算机科学证明的主力。证明循环不变量——「每轮迭代后某性质仍成立」——就是对迭代次数施归纳,这是程序正确性证明的核心。递归算法(归并排序、快速幂)的正确性几乎都靠结构归纳。类型系统的健全性、编译器优化的保序性、分布式协议的安全性证明,底层都是归纳。可以说,凡是涉及「对一切规模都成立」的软件保证,背后都站着归纳法。

一句话精华
归纳法把「验证无穷」折叠成「证明一个起点 + 一条不断链」。
思考题:有个著名的假证明「所有的马都同色」用归纳法推出荒谬结论。它的基础步和归纳步分别在哪里悄悄崩塌了?(提示:想想 $k=1 \to k=2$ 那一步。)

递归与递推

Recursion & Recurrence · 把问题定义在自己身上
Algorithms
直觉版

俄罗斯套娃:打开一个,里面是一个更小的、一模一样的娃娃,直到最里面那个小到打不开为止。递归就是这种结构——解决一个大问题的方法,是先解决一个更小的同类问题,一层层缩小,直到抵达一个「不用再想就知道答案」的最小情形(基例)。

如果说归纳法是「证明的向上爬」(从 $k$ 推到 $k{+}1$),递归就是「计算的向下钻」(把 $n$ 化归到 $n{-}1$)。它们是同一枚硬币的两面:归纳保证递归会终止且正确,递归则是归纳在计算世界里的化身。

正式定义
$$F(n)=F(n{-}1)+F(n{-}2),\qquad F(0)=0,\ F(1)=1$$

一个 递推关系 用较小的项定义当前项,再加上初始条件(基例)把链锚在地面上。上式是斐波那契数列——去掉初始条件,它只是一个空悬的规则;有了 $F(0),F(1)$,整个数列就被唯一确定。递归函数就是把这个定义直接翻译成代码:函数在自己体内调用自己,靠基例停下来。

F4 F3 F2 F2 F1 F1 F0 F1 F0 F2 被 重复算
为什么美

同一个递归可以有惊人不同的面孔。斐波那契的递推是最朴素的加法,可它的闭式解竟然是 $F(n)=\frac{\varphi^n-\psi^n}{\sqrt5}$,其中 $\varphi=\frac{1+\sqrt5}{2}$ 正是黄金比例——一个满是无理数、幂运算的公式,代进去每次都吐出整数。为什么一个只讲整数相加的规则,骨子里藏着黄金比例?因为递推关系对应一个特征方程 $x^2=x+1$,它的根就是 $\varphi$。递推的「增长基因」写在特征方程的根里——这是离散世界与代数、与连续增长率之间一座隐秘的桥。

应用

分治算法(归并排序、快速排序、FFT)就是「把问题劈成两半,各自递归,再合并」,其运行时间由递推 $T(n)=2T(n/2)+O(n)$ 描述,靠主定理一眼解出 $O(n\log n)$。动态规划 本质是「有重叠子问题的递归」——上图里 $F2$ 被重复计算,记忆化(把算过的存下来)就能把指数级的重复砍成线性。语法解析、分形生成、递归神经网络、乃至函数式编程的整个范式,都建在递归之上。

一句话精华
递归 = 把问题定义在自己身上;递归向下算,归纳向上证,是同一件事。
思考题:朴素递归算斐波那契是指数时间,加一句「记忆化」就变成线性时间。被省下的,究竟是什么?(提示:数一数递归树里有多少个节点是重复的。)

渐近复杂度(大 O)

Asymptotic Complexity · Big-O · 度量「扩展的命运」
Complexity
直觉版

你写了个程序,跑一次要 3 毫秒——这个数字几乎没用。换台机器、换个编译器,它就变了。真正决定命运的问题是:数据量翻倍时,时间怎么变?翻倍?还是翻四倍?还是原地不动?大 O 记号丢掉所有常数和低阶项,只保留「增长的形状」,因为当数据足够大时,唯有增长率是命运,常数只是噪声

一个 $O(n)$ 的笨算法配慢机器,长远看仍会碾压 $O(n^2)$ 的巧算法配快机器——只要 $n$ 够大。大 O 量的不是「此刻多快」,而是「扩展时会不会撞墙」。

正式定义
$$f(n)=O(g(n))\iff \exists\,c>0,\ n_0,\ \forall n>n_0:\ f(n)\le c\,g(n)$$

读作:当 $n$ 大过某个门槛 $n_0$ 之后,$f$ 永远被 $g$ 的某个常数倍 $c\,g(n)$ 压在下面。$c$ 吸收了所有硬件、常数因子的差异;$n_0$ 表示「我们只关心足够大的规模」。所以 $3n^2+100n+5 = O(n^2)$——低阶的 $100n$ 和常数 $5$ 在大 $n$ 面前全被淹没。大 O 是一副「只看趋势、不看细节」的眼镜。

n 时间 O(log n) O(n) O(n log n) O(n²) O(2ⁿ)
为什么美

大 O 让算法脱离机器、语言、年代,成为可以纯粹比较的数学对象。而它最震撼之处在于:不同的 O 之间不是「快一点慢一点」,而是「可行与不可行」的鸿沟。$O(n)$ 与 $O(n^2)$ 在 $n=10^6$ 时相差一百万倍;$O(n)$ 与 $O(2^n)$ 的差距则超越了宇宙原子数。这条「多项式 vs 指数」的分界线,正是理论计算机科学最深的悬案 P vs NP 的心脏——某些问题我们能验证答案,却似乎无法快速找到答案。一个记号,划开了「计算之可能」的边界。

应用

数据库为什么建索引?把查找从 $O(n)$ 的全表扫描降到 $O(\log n)$ 的 B 树——数据越大,差距越致命。哈希表用 $O(1)$ 平均查找支撑了几乎所有系统。而当下最鲜活的例子是大模型:Transformer 的自注意力是 $O(n^2)$(每个 token 看所有 token),这正是长上下文的瓶颈——FlashAttention、线性注意力、状态空间模型 的全部动机,就是把这个 $n^2$ 降下来。大 O 不是学院概念,它每天决定着能不能把上下文从 8K 拉到 100 万。

一句话精华
大 O 度量的是「扩展的命运」,不是「当下的速度」——增长率才是长跑的胜负手。
思考题:任何基于「两两比较」的排序算法,都逃不过 $O(n\log n)$ 的下界。为什么?(提示:$n$ 个元素有 $n!$ 种排列,每次比较最多把可能性砍一半。)

离散概率

Discrete Probability · 会数数的不确定性
Probability
直觉版

连续概率是「量面积」,离散概率是「数数」。你把所有可能的结果列成一张清单(样本空间),如果每个结果等可能,那么一个事件的概率,就是有利结果的个数 ÷ 结果总数。掷骰子出偶数?$3/6$。从一副牌抽到红桃?$13/52$。概率在这里退化成了纯粹的组合计数——会数数,就会算概率

正因如此,离散概率与组合数学是连体双生:算概率的难点,往往不在概率本身,而在「怎么把有利情况数清楚、又不重不漏」。

正式定义
$$P(A)=\frac{|A|}{|\Omega|}\ \text{(古典概型)},\qquad \mathbb{E}[X]=\sum_{x} x\cdot P(X{=}x)$$

$\Omega$ 是样本空间(所有结果的集合),$A\subseteq\Omega$ 是事件,$|A|$ 是它含的结果数。等可能时,概率就是两个计数之比。期望 $\mathbb{E}[X]$ 是随机变量 $X$ 的「加权平均」——把每个取值乘以它的概率再相加,代表「长期平均而言会得到多少」。它是离散概率里最有用的一个数。

为什么美

离散概率最优雅的武器是期望的线性性:$\mathbb{E}[X+Y]=\mathbb{E}[X]+\mathbb{E}[Y]$,无论 $X$ 与 $Y$ 是否独立。这看似平淡,威力却惊人——许多看上去要纠缠所有相关性的难题,一旦拆成一堆简单随机变量之和,各自求期望再相加,答案立刻浮现。比如「一副洗乱的牌,平均有多少张停在自己原来的位置」,直接算要面对复杂的相关性;用线性性,答案干净利落地等于 $1$。把不确定性拆成可以逐个数、再相加的小块——这是离散概率的核心美感。

应用

随机化是现代算法的秘密武器:随机化快排用「随机选主元」把最坏情况压到几乎不可能;哈希 靠随机分布实现负载均衡;Bloom 过滤器 等概率数据结构,用一点点可控的错误率换取巨大的空间节省。机器学习靠随机采样(mini-batch、dropout)训练,大模型生成时的「温度」正是在对下一个 token 的离散概率分布做采样。凡是要在不确定中做决策的地方,都是离散概率在支撑。

一句话精华
离散概率 = 会数数的不确定性;把复杂的随机拆成可相加的小块,是它最锋利的刀。
思考题:房间里只要 23 个人,就有超过 50% 的概率存在两人生日相同。为什么这个数字小得如此反直觉?(提示:关键不是「你和别人」,而是「所有配对」——$23$ 人有 $253$ 对。)

深入思考

归纳法能证明的,和它证不了的——界线在哪里?
归纳法只对良序结构有效——自然数、有限树、可数递归定义。对实数就失效了:实数没有「下一个数」,归纳步无从谈起。这引出超限归纳与序数,需要良序定理(等价于选择公理)来奠基。「归纳能走多远」这个问题,一路把我们推到集合论的地基处——它与 Day 11 的无穷、Day 12 的形式化直接相连。
递归、归纳、不动点,是不是同一个思想的三张脸?
递归定义($F$ 用自己定义)在数学上是在求一个不动点:满足 $F=\Phi(F)$ 的那个 $F$;归纳则保证它存在且唯一。λ 演算的 Y 组合子、Knaster–Tarski 不动点定理,讲的都是「自我引用如何被驯服成良定义」。而当自指失控,同一个结构就成了罗素悖论与哥德尔句子——用得好是递归,用得险是悖论。
为什么「多项式时间」被当作「高效」的分界线?
这是约定,却极稳健:多项式时间在组合下封闭,且不依赖具体计算模型(图灵机、RAM 互相模拟只差多项式)——即 Cobham–Edmonds 论题;指数时间则一碰就爆炸。P vs NP 问的正是:验证容易的问题,求解是否也容易?绝大多数人相信 $P\neq NP$,却无人能证——这是我们时代最重要的数学悬案,赏金一百万美元。
离散与连续,谁更基本?
物理世界看似连续(时空、场),但量子力学说能级是离散的,信息论说信息以比特为单位,而计算必须离散——图灵机只操作有限符号。离散数学与微积分(Day 3)像是描述同一实在的两种语言:差分之于微分,求和之于积分,递推之于微分方程。这层对偶本身,就是一个深刻的谜。