<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Donald Knuth on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/donald-knuth/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 08 Mar 2024 10:40:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/donald-knuth/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>《具体数学》笔记：给 TAOCP 打地基的那门课，把“算得出来”变成一种信仰</title>
      <link>https://ftmao.com/blog/bookstore/concrete-mathematics-book-notes/</link>
      <pubDate>Fri, 08 Mar 2024 10:40:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/concrete-mathematics-book-notes/</guid>
      <description>&lt;h1 id=&#34;具体数学笔记给-taocp-打地基的那门课把算得出来变成一种信仰&#34;&gt;《具体数学》笔记：给 TAOCP 打地基的那门课，把“算得出来”变成一种信仰&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;目标读者：被算法复杂度“大概是个 n log n”糊弄过、想学会把账算清楚的工程师；以及啃不动 TAOCP 数学小节、想找一本更友好的前传的人。
参考书籍：Ronald L. Graham、Donald E. Knuth、Oren Patashnik《具体数学：计算机科学基础》（Concrete Mathematics: A Foundation for Computer Science，1989 年初版，1994 年第二版）。
阅读目标：不是把九章全部复刻一遍——那等于重抄一本书——而是把每章的“核心技术”蒸馏成一张地图：每章解决什么问题、哪几个技巧值得练成肌肉记忆、哪些结论在工程里真的能变现。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一定位continuous--discrete一门为具体正名的课&#34;&gt;一、定位：continuous + discrete，一门为“具体”正名的课&lt;/h2&gt;
&lt;p&gt;先解书名的梗。&lt;strong&gt;Concrete&lt;/strong&gt; 是 &lt;strong&gt;CON&lt;/strong&gt;tinuous + dis&lt;strong&gt;CRETE&lt;/strong&gt; 的拼接文字游戏：这门课讲的是连续数学与离散数学之间那片“受控的混合地带”——和式、递推、取整、组合数、生成函数，全是既不离散得纯粹也不连续得抽象的对象。作者们在前言里说得很直白：这门课要教的是**“具体”的数学——能算出来的、能推广成闭式（closed form）的数学**，而不是那种只证明存在性、给不出数值的数学。&lt;/p&gt;
&lt;p&gt;这门课有真实的血统：它源自斯坦福自 1970 年起开设的同名课程，Knuth 本人讲过很多轮，最初就是为了给学计算机的学生补 TAOCP 所需的数学地基。三位作者里，Graham 是组合数学大家（“Graham 数”那个 Graham），Knuth 不必介绍，Patashnik 是 Knuth 的学生、BibTeX 的作者。这本书和 TAOCP 是天然的姊妹篇——TAOCP 里那些“易证，留给读者”的数学推导，这本书把它们摊开揉碎讲透。&lt;/p&gt;
&lt;p&gt;这本书还有一个别的教科书没有的特征：&lt;strong&gt;页边涂鸦（margin graffiti）&lt;/strong&gt;。每一页的页边都印着当年选课学生的批注、玩笑、吐槽和妙语——这是 Knuth 从课程助教的课堂记录里精选出来的，让整本书读起来像一间热闹的研讨室而不是一座庙。严肃内容与页边段子并置，本身就是作者的表态：数学是可以玩得起来的手艺，不是供奉起来的神像。&lt;/p&gt;
&lt;p&gt;这本书的习题也自成体系，按用途分六档：热身题（warmups，读完正文就该会做）、基本题（basics，巩固事实）、作业题（homework，加深理解）、考试题（exam problems，一题多概念）、加分题（bonus problems，超出正文范围）、研究题（research problems，出题时可能没有已知答案）。这个分档本身就是一张阅读路线图：时间紧就只做热身题和基本题，想深挖再往下走。另外交代一句版本差异：1994 年的第二版除了修订错误，还新增了超几何求和机械化（Zeilberger 对 Gosper 算法的扩展）等新材料——入手时注意对应第二版。&lt;/p&gt;
&lt;p&gt;阅读难度上给一个实话提示：这本书推导密度很高，但没有一处是“为难而难”——所有推导都服务于一个能算出来的结果。第一遍只读正文、把结论划线即可，习题先挑热身题做；真正让人回不去的是第二遍：当你发现工作里那个“算不清的复杂度”其实就是第 2 章的一道例题时，这本书就长在手边了。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    CM[&amp;#34;具体数学 Concrete Mathematics&amp;lt;br/&amp;gt;continuous + discrete&amp;#34;] --&amp;gt; R[&amp;#34;第 1-3 章 基本功&amp;lt;br/&amp;gt;递归 / 和式 / 整值函数&amp;#34;]
    CM --&amp;gt; N[&amp;#34;第 4-6 章 组合核心&amp;lt;br/&amp;gt;数论 / 二项式系数 / 特殊数&amp;#34;]
    CM --&amp;gt; G[&amp;#34;第 7-9 章 分析武器&amp;lt;br/&amp;gt;生成函数 / 离散概率 / 渐近&amp;#34;]
    R -.-&amp;gt;|&amp;#34;三板斧&amp;lt;br/&amp;gt;小情形-猜测-归纳&amp;#34;| TAOCP[&amp;#34;TAOCP 的数学地基&amp;lt;br/&amp;gt;算法精确分析&amp;#34;]
    N -.-&amp;gt;|&amp;#34;计数与恒等式&amp;#34;| TAOCP
    G -.-&amp;gt;|&amp;#34;从递推到闭式到量级&amp;#34;| TAOCP
    style TAOCP fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;二递归问题小规模情形--猜测--归纳证明&#34;&gt;二、递归问题：小规模情形 → 猜测 → 归纳证明&lt;/h2&gt;
&lt;p&gt;第 1 章用三个经典问题立起全书的方法论：&lt;strong&gt;先算小规模情形，大胆猜测一般规律，再用数学归纳法钉死它。&lt;/strong&gt; 这三板斧听起来朴素，但全书后面所有“神来之笔”都是这个套路的放大版。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[&amp;#34;小规模情形&amp;lt;br/&amp;gt;手算 n 等于 0,1,2,3&amp;#34;] --&amp;gt; B[&amp;#34;大胆猜测&amp;lt;br/&amp;gt;一般规律或闭式&amp;#34;]
    B --&amp;gt; C[&amp;#34;数学归纳法&amp;lt;br/&amp;gt;严格证明&amp;#34;]
    C --&amp;gt;|&amp;#34;证不出来&amp;lt;br/&amp;gt;回头修正猜测&amp;#34;| B
    C --&amp;gt; D[&amp;#34;得到可迁移的洞察&amp;lt;br/&amp;gt;而不只是数据&amp;#34;]
    style D fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;汉诺塔&lt;/strong&gt;：$n$ 个盘子的最少移动次数满足 $T_n = 2T_{n-1} + 1$，$T_0 = 0$，算几项猜出 $T_n = 2^n - 1$，归纳法一行收尾。这题的标准价值在于示范了“把大问题化归成同构的小问题”这个递归思维本身。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;汉诺塔变体&lt;/strong&gt;：书中接着玩规则——若规定盘子每次只能在相邻柱子间移动，答案变成 $3^n - 1$。同一个游戏，约束一改，闭式的底数从 2 变 3：递推结构决定一切。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平面分割直线（切披萨）&lt;/strong&gt;：$n$ 条直线最多把平面分成几块？第 $n$ 条直线最多与前面 $n-1$ 条各交一点，被切成 $n$ 段，每段多劈出一个区域：$L_n = L_{n-1} + n$，展开得 $L_n = n(n+1)/2 + 1$。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高维推广&lt;/strong&gt;：书中顺势把切披萨推到高维——$n$ 张平面最多把空间切成 $\binom{n}{0} + \binom{n}{1} + \binom{n}{2} + \binom{n}{3}$ 块，一般维度的答案都是二项式系数的截断和。这是二项式系数在第 5 章正式登场前的第一次亮相。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;约瑟夫问题（Josephus problem）&lt;/strong&gt;：$n$ 人围圈，每隔一人杀一人，最后幸存者的编号 $J(n)$ 是多少？这是全章的高潮。算小情形发现 $J(n)$ 总是奇数且按 $2$ 的幂分段线性，猜出并证明：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$$J(2^m + \ell) = 2\ell + 1, \qquad 0 \le \ell &amp;lt; 2^m$$&lt;/p&gt;
&lt;p&gt;真正的神来之笔是它的&lt;strong&gt;二进制形态&lt;/strong&gt;：把 $n$ 写成二进制 $n = (1\, b_{m-1} b_{m-2} \ldots b_0)_2$，则 $J(n)$ 就是把最高位的 $1$ 循环移到最低位——$J(n) = (b_{m-1} b_{m-2} \ldots b_0\, 1)_2$。一个看起来要模拟整个过程的问题，答案是一次&lt;strong&gt;循环左移&lt;/strong&gt;。这个结果是“猜小情形”方法论能给的最高奖赏：不光有闭式，还有一个看一眼就忘不掉的结构。&lt;/p&gt;
&lt;p&gt;书里也诚实地泼了冷水：把规则改成每隔两人杀一人，约瑟夫问题就没有这么漂亮的闭式了——&lt;strong&gt;漂亮的闭式是运气，小情形-猜测-归纳的方法论才是常态&lt;/strong&gt;。这个提醒对工程实践同样适用：先问有没有结构，再决定要不要追闭式。&lt;/p&gt;
&lt;p&gt;章末还埋了一个进阶武器：&lt;strong&gt;套招法（repertoire method）&lt;/strong&gt;。遇到带一般常数项的递推（比如 $f(1) = \alpha$、$f(2n) = 2f(n) + \beta$ 这类约瑟夫问题的推广式），先找一批函数已知、常数项也已知的“招式”作为基，再把目标常数项表成这些基的线性组合——解也就跟着线性组合出来。它和线性代数里“基展开”是同一件事，只不过向量换成了递推的解。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;感悟&lt;/strong&gt;：工程师遇到递推的第一反应常是“写个程序跑一下”。这一章的立场是：跑程序只能给你数据，&lt;strong&gt;归纳-猜测-证明&lt;/strong&gt;才能给你洞察——而洞察是可以迁移的，数据不能。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三和式扰动法与-iverson-括号&#34;&gt;三、和式：扰动法与 Iverson 括号&lt;/h2&gt;
&lt;p&gt;第 2 章把“求和”从小学算术升级成一套形式演算。&lt;/p&gt;
&lt;p&gt;**扰动法（perturbation method）**是本章的招牌技巧，以求几何级数为例：设 $S_n = \sum_{k=0}^{n} a x^k$，把最后一项拆出来再重新配齐下标，得到&lt;/p&gt;
&lt;p&gt;$$S_n + a x^{n+1} = a + x S_n \quad\Longrightarrow\quad S_n = \frac{a - a x^{n+1}}{1 - x}$$&lt;/p&gt;
&lt;p&gt;整个过程没有一个“聪明的灵感”，纯粹是把和式当作可以代数操作的符号对象——这就是“形式方法”的力量：把直觉题变成机械题。等差数列和、算术-几何混合级数，同一个套路通吃。本质上它是“把未知量凑进自己的方程里再解出来”，和代数里的移项是同一个思想，只是操作对象从数换成了和式。&lt;/p&gt;
&lt;p&gt;同一个动作还能解递推。书中用**求和因子法（summation factor）**处理 $a_n T_n = b_n T_{n-1} + c_n$ 型的一阶递推，并用它解出快速排序的平均比较次数：递推 $C_n = n + 1 + \frac{2}{n}\sum_{k&amp;lt;n} C_k$ 的精确解是 $C_n = 2(n+1)H_n - 4n$——教科书里“快排平均 $O(n \log n)$”这句话的完整账，就长这样。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多重和式交换求和次序&lt;/strong&gt;是另一项基本功：$\sum_i \sum_j a_{ij}$ 先加哪个，取决于哪个方向好算——这和数据库优化器决定 join 顺序是同构的思维。配上 Iverson 括号，这个技巧变得完全机械：界限互相依赖的双重和可以写成&lt;/p&gt;
&lt;p&gt;$$\sum_j \sum_k a_{j,k}\,[1 \le j \le k \le n]$$&lt;/p&gt;
&lt;p&gt;界限信息全部进括号之后，交换次序就退化成对括号里的条件做代数变换，不再需要在脑子里维护“哪一层界限依赖哪个下标”。&lt;/p&gt;
&lt;p&gt;然后是全书影响力最大的记号发明之一：&lt;strong&gt;Iverson 括号（Iverson&amp;rsquo;s convention）&lt;/strong&gt;。对任意命题 $P$：&lt;/p&gt;
&lt;p&gt;$$[P] = \begin{cases} 1, &amp;amp; P \text{ 为真} \\ 0, &amp;amp; P \text{ 为假} \end{cases}$$&lt;/p&gt;
&lt;p&gt;（源码里上面 cases 环境的换行写作 &lt;code&gt;\\\\&lt;/code&gt;，这是本站 KaTeX 渲染链路的转义要求，不是笔误。）Iverson 括号的威力在于&lt;strong&gt;消灭求和界限上的特例讨论&lt;/strong&gt;：比如“小于 $n$ 的素数个数”可以不带任何附加条件地写成 $\sum_{0 \le k &amp;lt; n}[k \in \mathbb{P}]$，求和范围随便切，条件全部进括号。这个记号源自 Ken Iverson 的 APL 语言，由 Knuth 大力推广——它是编程思想（布尔值即 0/1）反哺数学记号的典范。&lt;/p&gt;
&lt;p&gt;第 2 章的后半还有一套常被跳过的重武器：&lt;strong&gt;有限微积分（finite calculus）&lt;/strong&gt;。定义差分算子 $\Delta f(x) = f(x+1) - f(x)$，它是导数的离散对应；再定义&lt;strong&gt;下降阶乘幂&lt;/strong&gt; $x^{\underline{m}} = x(x-1)\cdots(x-m+1)$（共 $m$ 个递减因子），则有一条漂亮的平行定理：$\Delta(x^{\underline{m}}) = m\,x^{\underline{m-1}}$，对应的不定和公式 $\sum_{0 \le k &amp;lt; n} k^{\underline{m}} = n^{\underline{m+1}}/(m+1)$ 就是幂函数积分的离散版。普通幂拆成下降幂（比如 $k^2 = k^{\underline{2}} + k^{\underline{1}}$）之后，平方和公式三行就出来了；章末的**分部求和（summation by parts）**则把分部积分整套搬了过来。有限微积分的意义在于：&lt;strong&gt;一整类多项式与阶乘幂的求和变成了查表，不再需要每题一灵感。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最后补一条书中反复强调的边界：以上所有形式操作默认和式是有限或绝对收敛的。对无穷和式随意交换次序、随意套用扰动，会撞上经典悖论——&lt;strong&gt;形式方法的自由是有边界的，边界叫收敛性。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四整值函数与数论floorceiling-与欧几里得&#34;&gt;四、整值函数与数论：floor、ceiling 与欧几里得&lt;/h2&gt;
&lt;p&gt;第 3 章处理一个工程师天天用、却很少细想的对象：下取整 $\lfloor x \rfloor$ 与上取整 $\lceil x \rceil$。核心性质几条就够日常防身：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;界定：$x - 1 &amp;lt; \lfloor x \rfloor \le x$；镜像关系 $\lceil x \rceil = -\lfloor -x \rfloor$；&lt;/li&gt;
&lt;li&gt;判定式：$\lfloor x \rfloor = n$ 当且仅当 $n \le x &amp;lt; n+1$——这条“把取整翻译成不等式”的等价式是证明一切 floor 恒等式的钥匙；&lt;/li&gt;
&lt;li&gt;整数进出：$\lfloor x + n \rfloor = \lfloor x \rfloor + n$（整数可以自由进出取整号）——看似显然，却是 floor 恒等式证明里被用得最多的动作；&lt;/li&gt;
&lt;li&gt;取模的定义式：$x \bmod y = x - y\lfloor x/y \rfloor$，它让 $\bmod$ 在负数和小数上也有确定含义；&lt;/li&gt;
&lt;li&gt;同余的代数：$(a + b) \bmod m$ 可以先各自取模再相加（乘法同理）——这是大数计算不溢出、哈希设计不散架的基本功。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第 3 章还有一类硬功夫是&lt;strong&gt;含 floor/ceiling 的和式&lt;/strong&gt;：把求和区间按 floor 值的变化点切开（“区间划分”技巧），一个看似无规律的取整和就被拆成几段普通和式。本章最让人意外的收尾是&lt;strong&gt;瑞利定理（Beatty 序列，又称谱定理）&lt;/strong&gt;：若 $\alpha, \beta$ 是正无理数且 $1/\alpha + 1/\beta = 1$，则两个序列 $\lfloor n\alpha \rfloor$ 与 $\lfloor n\beta \rfloor$（$n = 1, 2, 3, \ldots$）不重不漏地恰好划分全体正整数——取整这种“坑坑洼洼”的运算，竟然能产出完美的划分。&lt;/p&gt;
&lt;p&gt;第 4 章进入数论，主线清晰：整除与最大公约数、素数与唯一分解定理、互素与欧拉 $\varphi$ 函数、模运算。章首的技术核心是&lt;strong&gt;欧几里得算法&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;$$\gcd(m, n) = \gcd(n,\, m \bmod n)$$&lt;/p&gt;
&lt;p&gt;及其扩展形式（把 $\gcd$ 表成 $m&amp;rsquo; m + n&amp;rsquo; n$ 的线性组合）。唯一分解定理（每个正整数分解为素数幂的乘积且方式唯一）是全章的地基，阶乘中素因子次数的计算（Legendre 公式：$n!$ 中素数 $p$ 的次数为 $\sum_{k \ge 1} \lfloor n/p^k \rfloor$）是它的漂亮应用。$\varphi(n)$ 计“与 $n$ 互素的剩余类个数”，乘性公式 $\varphi(n) = n \prod_{p \mid n}(1 - 1/p)$ 一条就够记住。&lt;/p&gt;
&lt;p&gt;这一章还有三件值得单独记住的东西：一是&lt;strong&gt;约数求和恒等式&lt;/strong&gt; $\sum_{d \mid n} \varphi(d) = n$——把 $1$ 到 $n$ 按“与 $n$ 的最大公约数”分桶即可一行证出；二是 &lt;strong&gt;Stern-Brocot 树&lt;/strong&gt;：从 $0/1$ 与 $1/0$ 两个哨兵出发，不断插入相邻分数的中位分数（mediant）$\frac{m+m&amp;rsquo;}{n+n&amp;rsquo;}$，能生成全部正有理数，每个恰好一次且自动是最简形式——这是连分数与有理逼近理论的入口；三是&lt;strong&gt;中国剩余定理的一个具体例子&lt;/strong&gt;：模 3 余 2、模 5 余 3 的数，在模 15 意义下被唯一确定（就是 8）——一般定理不过是这个例子的机械推广，书里强调的思想是&lt;strong&gt;局部余数信息可以无损拼出全局&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五二项式系数恒等式的丛林与机械化证明&#34;&gt;五、二项式系数：恒等式的丛林与机械化证明&lt;/h2&gt;
&lt;p&gt;第 5 章是全书最厚、也最容易迷路的一章：二项式系数的恒等式多到像丛林。正确的读法是抓住少数几条“母恒等式”，其余都是它们的子女。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定义与基本款：$\binom{n}{k} = \binom{n}{n-k}$（对称），加法公式 $\binom{n}{k} = \binom{n-1}{k} + \binom{n-1}{k-1}$（帕斯卡三角的生成规则），吸收恒等式 $k\binom{n}{k} = n\binom{n-1}{k-1}$（把下标里的 $k$ 吸出去）。&lt;/li&gt;
&lt;li&gt;平行求和（曲棍球棒恒等式）：$\sum_{0 \le k \le n} \binom{r+k}{k} = \binom{r+n+1}{n}$——沿帕斯卡三角斜着加，和落在下一行，是处理“带前缀的二项式求和”的第一反应。&lt;/li&gt;
&lt;li&gt;二项式定理：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$$(x + y)^n = \sum_{k=0}^{n} \binom{n}{k} x^k y^{n-k}$$&lt;/p&gt;
&lt;p&gt;令 $x = y = 1$ 得全体二项系数之和为 $2^n$；令 $x = -1$ 得交错和为 $0$——“代入特殊值”本身就是制造恒等式的流水线。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;三项式系数与多项式定理是二项式的直接推广，拆开字母逐个分配即可。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;丛林里还有两条路标值得记住：&lt;strong&gt;范德蒙德卷积&lt;/strong&gt; $\sum_{k} \binom{r}{k}\binom{s}{n-k} = \binom{r+s}{n}$——组合解释是“从 $r+s$ 个元素里选 $n$ 个，按从第一堆里选了几个分类”，它展示了组合论证与代数恒等式的互译；&lt;strong&gt;上指标取反&lt;/strong&gt; $\binom{r}{k} = (-1)^k \binom{k-r-1}{k}$，把上指标推广到负数，是生成函数展开里处理负幂的常备变换。&lt;/p&gt;
&lt;p&gt;这一章真正的“现代”内容在末尾：大量二项式恒等式可以写成&lt;strong&gt;超几何级数&lt;/strong&gt;的标准形式，而 &lt;strong&gt;Gosper 算法&lt;/strong&gt;能机械地判定一个超几何项是否有闭式不定和、有就直接算出来——也就是说，曾经需要灵感的恒等式证明，有相当大一类已经&lt;strong&gt;被算法化了&lt;/strong&gt;。这是全书精神最锋利的一次展示：连“证明数学恒等式”这件事本身都可以具体化、机械化。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六特殊数给高频出现的数建档案&#34;&gt;六、特殊数：给高频出现的数建档案&lt;/h2&gt;
&lt;p&gt;第 6 章给一批在计数问题里反复冒头的“特殊数”立档案，每个都值一行记住：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;斯特林数&lt;/strong&gt;分两类，记住口诀“子集与轮换”：第二类 $\left\{ {n \atop k} \right\}$ 是把 $n$ 个元素划分成 $k$ 个非空子集的方案数；第一类 $\left[ {n \atop k} \right]$ 是把 $n$ 个元素排成 $k$ 个轮换的方案数。第二类的递推是 $\left\{ {n \atop k} \right\} = k \left\{ {n-1 \atop k} \right\} + \left\{ {n-1 \atop k-1} \right\}$——第 $n$ 个元素要么自立门户，要么加入已有 $k$ 个子集之一。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;斯特林数还是翻译器&lt;/strong&gt;：$x^n = \sum_{k} \left\{ {n \atop k} \right\} x^{\underline{k}}$，普通幂与下降阶乘幂之间的互译靠它完成——这一式把第 2 章的有限微积分和本章的计数数列缝在了一起。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;欧拉数&lt;/strong&gt;数的是排列中“上升”的个数——这是分析插入类排序时会自然冒出来的数。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调和数&lt;/strong&gt; $H_n = \sum_{k=1}^{n} \frac{1}{k}$，全书最重要的渐近式之一：$H_n = \ln n + \gamma + O(1/n)$，其中 $\gamma$ 是欧拉常数。快速排序平均比较次数、优惠券收集问题，答案里全是 $H_n$。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;斐波那契数&lt;/strong&gt;：$F_n = F_{n-1} + F_{n-2}$，下一章用生成函数一次性解出闭式；顺记其渐近：$F_n$ 最接近 $\phi^n/\sqrt{5}$，增长率由黄金比例封顶。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卡塔兰数&lt;/strong&gt; $C_n = \frac{1}{n+1}\binom{2n}{n}$：合法括号序列、二叉树形状数、栈置换数——凡是“任意前缀中左括号不少于右括号”的计数，答案都是它。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一章的读法是当字典用：不必一次背下所有递推，但要建立“这个长相的问题答案里会出现哪种数”的条件反射。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七生成函数把数列打包成幂级数&#34;&gt;七、生成函数：把数列打包成幂级数&lt;/h2&gt;
&lt;p&gt;第 7 章是全书皇冠。思想一句话：&lt;strong&gt;把数列 $g_0, g_1, g_2, \ldots$ 打包成幂级数 $G(z) = \sum_{n \ge 0} g_n z^n$&lt;/strong&gt;。打包之后，对数列的操作全部翻译成对级数的代数运算——这就是我私下叫它“数列的 DSL”的原因：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    S[&amp;#34;数列操作&amp;#34;] --&amp;gt; T[&amp;#34;生成函数对应物&amp;#34;]
    S1[&amp;#34;整体平移下标&amp;#34;] --&amp;gt; T1[&amp;#34;乘或除以 z&amp;#34;]
    S2[&amp;#34;逐项乘 n&amp;#34;] --&amp;gt; T2[&amp;#34;求导再乘 z&amp;#34;]
    S3[&amp;#34;两个数列卷积&amp;#34;] --&amp;gt; T3[&amp;#34;两个级数相乘&amp;#34;]
    S4[&amp;#34;前缀和&amp;#34;] --&amp;gt; T4[&amp;#34;乘 1/(1-z)&amp;#34;]
    style T fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;常用生成函数其实就一小张表：$\frac{1}{1-z} = \sum_{n \ge 0} z^n$ 对应全 1 数列，$\frac{1}{(1-z)^2} = \sum_{n \ge 0} (n+1) z^n$ 对应自然数序列，$e^z = \sum_{n \ge 0} z^n/n!$ 是指数生成函数的入口。背下这三条，再配上平移、求导、卷积三个操作，大多数有理型生成函数都能徒手展开。&lt;/p&gt;
&lt;p&gt;解递推的标准流水线因此变成纯机械三步：递推两边乘 $z^n$ 求和 → 解出 $G(z)$ 的有理式 → 部分分式展开读系数。斐波那契是标准演示：递推代入得 $F(z) = \frac{z}{1 - z - z^2}$，分母用黄金比例 $\phi = \frac{1+\sqrt{5}}{2}$ 与 $\hat{\phi} = \frac{1-\sqrt{5}}{2}$ 因式分解，部分分式后读出&lt;strong&gt;比内公式（Binet formula）&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;$$F_n = \frac{\phi^n - \hat{\phi}^n}{\sqrt{5}}$$&lt;/p&gt;
&lt;p&gt;卡塔兰数则是卷积解法的标准演示：由递推 $C_{n+1} = \sum_{k} C_k C_{n-k}$ 知生成函数满足二次方程 $C(z) = 1 + z\,C(z)^2$，解出 $C(z) = \frac{1 - \sqrt{1-4z}}{2z}$，再用广义二项式定理展开读系数，$\frac{1}{n+1}\binom{2n}{n}$ 就掉出来了。&lt;/p&gt;
&lt;p&gt;整章的信息量很大，但骨架就是这一句：&lt;strong&gt;递推是数列的“源码”，生成函数是编译器，闭式是编译产物。&lt;/strong&gt; 卷积对应乘法则让生成函数同时成为计数工具——把“选法”按规模分母，乘起来就读出组合方案数。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八离散概率与渐近期望的算术与-o-的纪律&#34;&gt;八、离散概率与渐近：期望的算术与 O 的纪律&lt;/h2&gt;
&lt;p&gt;第 8 章把概率论限制在离散空间重做一遍：随机变量是样本空间上的函数，期望线性性（哪怕变量不独立也成立）是本章最锋利的工具，方差度量散布。三个工程味十足的计算实例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优惠券收集&lt;/strong&gt;：集齐 $n$ 种优惠券的期望购买次数是 $E = n H_n$——把过程按“已收集到 $k$ 种”切成 $n$ 个阶段，每阶段是几何分布，期望直接相加。这是期望线性性最经典的演示：变量不独立也没关系，期望照样可加。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生日悖论&lt;/strong&gt;：$n$ 个人生日全不同的概率是 $P = \prod_{k=1}^{n-1}(1 - k/365)$，代入数值可知 23 人左右就跌破一半——所有用随机 ID 的系统都该对这个数有直觉。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;哈希分析&lt;/strong&gt;：拉链法下，设装填因子 $\alpha = n/m$，成功查找的平均探查次数用期望线性性直接算出，约为 $1 + \alpha/2$——装填因子是唯一旋钮，这个式子就是哈希表扩容阈值的理论出处。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;概率生成函数&lt;/strong&gt; $G_X(z) = \sum_{k} P(X = k)\, z^k$ 把第 7 章的机器整套搬进概率：分布的各阶矩可以从导数里读出，均值 $E(X) = G&amp;rsquo;_X(1)$，方差 $\mathrm{Var}(X) = G&amp;rsquo;&amp;rsquo;_X(1) + G&amp;rsquo;_X(1) - (G&amp;rsquo;_X(1))^2$——算矩变成了求导加代值的机械操作。注意一个不对称：期望可加不需要独立性，方差可加却需要（准确说是不相关）——这是实战里最容易踩的坑。&lt;/p&gt;
&lt;p&gt;独立随机变量之和的概率生成函数等于各自生成函数的乘积——“独立和”在生成函数世界里就是乘法，这是卷积对应的概率版本，也是分析“多次独立试验总代价”的标准入口。&lt;/p&gt;
&lt;p&gt;第 9 章给“量级”立规矩。大 O 的精确定义：$f(n) = O(g(n))$ 当且仅当存在常数 $C$ 使 $|f(n)| \le C|g(n)|$ 在定义域上成立。运算规则要当语法记：$O(f) + O(g) = O(f + g)$，$O(f) \cdot O(g) = O(f \cdot g)$，常数因子被吸收即 $O(C f) = O(f)$。常见坑书里都点了名：&lt;strong&gt;等号只能从左往右读&lt;/strong&gt;——$n^2 = O(n^3)$ 合法，反过来写是语法错误；O 里藏着看不见的常数，所以“两个实现同为 O(n)”不包含任何比较信息。&lt;strong&gt;O 不是一个值，是一个吸收记号。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;书里顺带给出一张该背下来的量级阶梯：$\log n \prec n \prec n \log n \prec n^2 \prec 2^n \prec n!$（$\prec$ 表示“渐近意义上严格小”）。遇到复杂表达式先把各项归到这条阶梯上，主次立刻分明——这是渐近分析的第一直觉训练。&lt;/p&gt;
&lt;p&gt;尾式交换（tail swap）是本章一个漂亮的通用技巧：当一个和式的尾部难算时，利用被求和量的对称性或单调性，把尾部换成结构相同但好算的镜像部分——很多“首尾呼应”的恒等式证明背后都是这一招。&lt;/p&gt;
&lt;p&gt;章尾是两件重器：&lt;strong&gt;欧拉求和公式&lt;/strong&gt;和&lt;strong&gt;斯特林渐近公式&lt;/strong&gt;。欧拉求和公式的一阶形态是&lt;/p&gt;
&lt;p&gt;$$\sum_{a \le k &amp;lt; b} f(k) = \int_a^b f(x)\, dx + \frac{f(a) + f(b)}{2} + \cdots$$&lt;/p&gt;
&lt;p&gt;它把“用积分逼近和式”从粗略估计变成带修正项的严格展开；令 $f(x) = \ln x$ 代入并对误差项做渐近分析，就得到斯特林公式：&lt;/p&gt;
&lt;p&gt;$$n! \sim \sqrt{2\pi n}\, (n/e)^n$$&lt;/p&gt;
&lt;p&gt;取对数即 $\ln n! = n\ln n - n + O(\log n)$——排序下界 $n \log n$ 里的那个 $n \log n$ 就是从这里来的，接上了 TAOCP 卷 3 的信息论论证。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九落到工程实践这本书改变了什么&#34;&gt;九、落到工程实践：这本书改变了什么&lt;/h2&gt;
&lt;p&gt;九章的武器收拢成日常纪律，一共七条：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;什么时候值得求闭式解。&lt;/strong&gt; 容量规划、复杂度精算、协议参数推导——凡是“答案要进 Excel 或设计文档”的场合，闭式解比模拟程序值钱：它能代入、能求导、能看出参数敏感度。反过来，一次性的、答案只用一个数值的问题，别硬求闭式，直接算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iverson 括号是代码评审的语言。&lt;/strong&gt; “当 x 为偶数且未越界时累加”这类口头描述歧义丛生，写成 $\sum_k a_k [k \text{ 为偶数}][k &amp;lt; n]$ 就没有歧义。评审里坚持“把条件写成显式谓词”，是从这一章借来的纪律。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成函数当 DSL 用。&lt;/strong&gt; 遇到“按规模计数”的需求（消息组合数、状态转移路径数），先想能不能写出递推；能写出递推，生成函数流水线就是确定的求解路径，不必靠灵感。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;渐近思维的纪律与大 O 滥用。&lt;/strong&gt; “这是 O(n²)”不是分析的终点：常数多大、输入规模落在哪个区间、低阶项什么时候反超，第 9 章训练的就是这种追问。见过太多拿大 O 当挡箭牌、把 $100n$ 和 $n^2/100$ 在 $n = 1000$ 下混为一谈的事故。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;扰动法与区间划分可以直接进性能分析。&lt;/strong&gt; 循环里带取整、带分支条件的代价累加，本质上就是含 floor 的和式：按跳跃点切开区间分段求和，比“拍个上界”准确得多。第 2、3 章的技巧是精确复杂度分析的扳手。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;机械化证明改变了“恒等式”的处境。&lt;/strong&gt; Gosper 算法的存在意味着：评审一个组合恒等式时先问“这能不能机判”，能机判的就不值得人肉推导——把人的精力留给机判不了的部分。这个分工原则对一切“已被算法化的技能”都成立。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对“算得出来”的信仰。&lt;/strong&gt; 这本书最深的影响是态度上的：遇到和式、递推、取整，默认它是&lt;strong&gt;可以算&lt;/strong&gt;的，只是还没找到对的技巧。把“大概”“估计”换成“我算算看”，是这本书送给工程师最好的礼物。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;本篇小结&#34;&gt;本篇小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;书名 Concrete 是 continuous + discrete 的文字游戏：教的是“能算出来、能推广成闭式”的数学；源自斯坦福课程，是 TAOCP 的数学地基；页边涂鸦与习题六档分级是这本书独有的气质与路线图。&lt;/li&gt;
&lt;li&gt;第 1 章立方法论：小情形 → 猜测 → 归纳证明，外加套招法；约瑟夫问题的答案是二进制循环左移，$J(2^m+\ell) = 2\ell+1$；漂亮闭式是运气，方法论是常态。&lt;/li&gt;
&lt;li&gt;第 2-3 章是基本功：扰动法与求和因子（快排平均比较次数 $2(n+1)H_n - 4n$ 就是这么算出来的）、Iverson 括号消灭特例讨论、有限微积分把求和变查表、floor/ceiling 的不等式翻译与区间划分、瑞利定理。&lt;/li&gt;
&lt;li&gt;第 4-6 章是组合核心：欧几里得算法与唯一分解、Stern-Brocot 树、二项式恒等式丛林与 Gosper 机械化证明、斯特林数/调和数/斐波那契/卡塔兰数档案。&lt;/li&gt;
&lt;li&gt;第 7-9 章是分析武器：生成函数把递推编译成闭式（Binet 公式是标准产物）、期望线性性算优惠券收集与生日悖论、概率生成函数算矩、大 O 的精确定义与运算语法、欧拉求和公式推出斯特林渐近。&lt;/li&gt;
&lt;li&gt;工程落地一句话：该求闭式时别满足于模拟，该谈常数时别躲进大 O。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这本书和 TAOCP 放在一起读效果最好：TAOCP 告诉你账要算，这本书教你账怎么算。读完后我写性能分析报告的习惯变了——先递推，再闭式，最后才轮到 profiler。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ronald L. Graham, Donald E. Knuth, Oren Patashnik, &lt;em&gt;Concrete Mathematics: A Foundation for Computer Science&lt;/em&gt;, 2nd ed., Addison-Wesley, 1994（初版 1989）。中译本《具体数学：计算机科学基础》，人民邮电出版社。&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &amp;ldquo;Two Notes on Notation&amp;rdquo;, &lt;em&gt;American Mathematical Monthly&lt;/em&gt;, 1992（Iverson 括号与斯特林数记号的推广短文）。&lt;/li&gt;
&lt;li&gt;Ralph W. Gosper, Jr., &amp;ldquo;Decision procedure for indefinite hypergeometric summation&amp;rdquo;, &lt;em&gt;Proceedings of the National Academy of Sciences&lt;/em&gt;, 1978（第 5 章机械化证明的原始论文）。&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 1（本书是其中数学预备知识的完整展开）。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>《计算机程序设计艺术》笔记：Knuth 用半个世纪给算法写的一部《史记》</title>
      <link>https://ftmao.com/blog/bookstore/taocp-book-notes/</link>
      <pubDate>Fri, 08 Dec 2023 10:40:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/taocp-book-notes/</guid>
      <description>&lt;h1 id=&#34;计算机程序设计艺术笔记knuth-用半个世纪给算法写的一部史记&#34;&gt;《计算机程序设计艺术》笔记：Knuth 用半个世纪给算法写的一部《史记》&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;目标读者：被&amp;quot;要不要读 TAOCP&amp;quot;这个问题折磨过的工程师；也想给正在啃这套书的人一张地图和一份劝退/劝进并存的导读。
参考书籍：Donald E. Knuth《计算机程序设计艺术》（The Art of Computer Programming）：卷 1《基本算法》（1968）、卷 2《半数值算法》（1969）、卷 3《排序与查找》（1973）、卷 4A《组合算法（一）》（2011），以及陆续以分册（fascicle）形式发布的 4B、4C。
阅读目标：不假装自己通读了这套书——说实话，没人通读过——而是把它读成一张&amp;quot;算法领域的地形图&amp;quot;：每卷解决什么问题、Knuth 的方法论是什么、哪些内容今天仍是工程师的硬通货、正确的打开姿势是什么。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一定位这不是教材是算法学科的史记&#34;&gt;一、定位：这不是教材，是算法学科的《史记》&lt;/h2&gt;
&lt;p&gt;先破一个流传最广的误读：TAOCP 不是&amp;quot;编程教程&amp;quot;，甚至不是&amp;quot;算法教材&amp;quot;。它是 Knuth 从 1962 年开始写的一部&lt;strong&gt;算法领域的编年史加分析法典&lt;/strong&gt;——每一种重要算法都给出精确的描述、完整的正确性论证、严格的运行时间分析，以及详尽到令人发指的文献考证。Bill Gates 那句著名的话是对这套书最准确的注脚：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;如果你觉得自己是个足够优秀的程序员，就去读 Knuth 的《计算机程序设计艺术》……如果你能读完它，请一定把简历发给我。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这句话的重点不在&amp;quot;读完&amp;quot;，在&amp;quot;读完的人值得收简历&amp;quot;——它说的是这套书的密度。Knuth 自己的写作史也配得上这份密度：1962 年动笔时他以为自己写的是一本&amp;quot;编译器构造&amp;quot;的书，越写发现底料越多，最终膨胀成七卷规划；卷 1 到卷 3 在 1968-1973 年间出齐，然后卷 4 一写就是近四十年，2011 年才出了 4A，至今仍在以分册形式连载。顺带一个工程师会心一笑的插曲：1977 年卷 2 出第二版时，出版商改用照相排版，Knuth 对数学公式的排版质量忍无可忍，于是&lt;strong&gt;自己花了近十年写了 TeX 排版系统&lt;/strong&gt;——全世界数学论文的排版标准，是这套书的副产品。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    TAOCP[&amp;#34;TAOCP 七卷规划&amp;lt;br/&amp;gt;1962 年动笔&amp;#34;] --&amp;gt; V1[&amp;#34;卷 1 基本算法 1968&amp;lt;br/&amp;gt;数学基础 + 数据结构&amp;#34;]
    TAOCP --&amp;gt; V2[&amp;#34;卷 2 半数值算法 1969&amp;lt;br/&amp;gt;随机数 + 高精度算术&amp;#34;]
    TAOCP --&amp;gt; V3[&amp;#34;卷 3 排序与查找 1973&amp;lt;br/&amp;gt;内排序 + 外排序 + 查找&amp;#34;]
    TAOCP --&amp;gt; V4[&amp;#34;卷 4 组合算法&amp;lt;br/&amp;gt;4A 2011 已出&amp;lt;br/&amp;gt;4B/4C 分册连载中&amp;#34;]
    TAOCP --&amp;gt; V5[&amp;#34;卷 5-7 规划中&amp;lt;br/&amp;gt;句法算法 / 语言理论等&amp;#34;]
    V1 -.-&amp;gt;|&amp;#34;排版质量事故&amp;#34;| TEX[&amp;#34;副产品: TeX&amp;lt;br/&amp;gt;全世界数学排版标准&amp;#34;]
    style TEX fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;为什么用-mixmmix-汇编而不是高级语言&#34;&gt;为什么用 MIX/MMIX 汇编，而不是高级语言&lt;/h3&gt;
&lt;p&gt;这是理解全书方法论的一把钥匙。书里所有算法都用一台假想计算机 &lt;strong&gt;MIX&lt;/strong&gt;（后来升级为 64 位 RISC 风格的 &lt;strong&gt;MMIX&lt;/strong&gt;）的机器语言写成。Knuth 给的理由，本质上是三条工程判断：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;要算性能账，就得有一台确定的机器&lt;/strong&gt;。算法分析的核心是精确计算执行次数和时间，而&amp;quot;这条语句花多少时间&amp;quot;在高级语言里是说不清的——编译器、运行时、指令集全在中间隔着。MIX 是一台指令集、时序完全定义好的机器，每条指令几个时钟周期白纸黑字，运行时间的分析因此可以&lt;strong&gt;精确到指令级&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;机器语言不赶时髦&lt;/strong&gt;。1960 年代的高级语言换得飞快（Algol、Fortran、PL/I……），用任何一种写书都会很快过时；而一台假想的、设计得足够经典的机器，五十年不过时。事实证明他赌对了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;逼你看清代价&lt;/strong&gt;。用汇编写，每一次访存、每一次循环、每一条跳转都暴露在纸面上——Knuth 认为程序员必须知道自己写的每一行代码让机器做了什么，这是&amp;quot;程序设计艺术&amp;quot;里&amp;quot;艺术&amp;quot;二字的底线。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;代价也是显然的：阅读门槛被这道汇编抬得很高。这也是为什么本文后面会专门谈&amp;quot;怎么读&amp;quot;——这套书的正确打开方式不是从第一页硬啃。&lt;/p&gt;
&lt;p&gt;另一个体现 Knuth 写作态度的细节是&lt;strong&gt;勘误奖励&lt;/strong&gt;：他给每个在书中首次发现错误的人签发一张&amp;quot;十六进制一美元&amp;quot;的支票（0x$1.00 = 2.56 美元）。钱少到可笑，但这张支票在技术圈是荣誉勋章——它宣示的是一种工程文化：&lt;strong&gt;错误不是羞耻，藏着掖着才是；每一版书都比上一版更接近正确。&lt;/strong&gt; 半个世纪几十个印次，这套书可能是人类历史上被校对得最狠的技术著作。&lt;/p&gt;
&lt;p&gt;还有一个容易忽略的风格特征：几乎每一节结尾都有 &lt;strong&gt;&amp;ldquo;History and bibliography&amp;rdquo;（历史与文献）&lt;/strong&gt; 小节，把这个算法从最早的雏形到最新的改进逐年考证，作者、年份、原始论文一个不落。这让 TAOCP 同时是一部&lt;strong&gt;算法史的目录&lt;/strong&gt;——想知道某个思想的最早出处，查这套书通常比查搜索引擎可靠。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二卷-1基本算法算法的定义与数据结构的奠基&#34;&gt;二、卷 1《基本算法》：算法的定义与数据结构的奠基&lt;/h2&gt;
&lt;h3 id=&#34;算法是什么五个特征与欧几里得算法&#34;&gt;算法是什么：五个特征与欧几里得算法&lt;/h3&gt;
&lt;p&gt;卷 1 开篇就干了件&amp;quot;法典&amp;quot;该干的事：给&amp;quot;算法&amp;quot;下定义。Knuth 用**算法 E（欧几里得求最大公约数）**做标本，提炼出算法的五个特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;有穷性（Finiteness）&lt;/strong&gt;：算法必须在有限步内终止。（Knuth 特别注明：只满足其余四条而不满足有穷性的，可以叫&amp;quot;计算方法&amp;quot;，比如某些永不终止但仍有用处的反应式过程。）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;确切性（Definiteness）&lt;/strong&gt;：每一步都必须精确定义、无歧义——自然语言描述做不到这一点，这是书里坚持用形式化记号的原因。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入（Input）&lt;/strong&gt;：有零个或多个输入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出（Output）&lt;/strong&gt;：有一个或多个输出，且与输入有确定关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能行性（Effectiveness）&lt;/strong&gt;：每一步都必须足够基本，原则上能用纸笔在有限时间内完成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个定义的价值在于它立刻产生了区分能力：菜谱通常不满足确切性（&amp;ldquo;适量盐&amp;rdquo;），死循环程序不满足有穷性，而&amp;quot;掷骰子决定下一步&amp;quot;不满足确切性——都不是算法。&lt;strong&gt;定义不是用来背的，是用来划界的。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;数学基础与-oωθ-的来历&#34;&gt;数学基础与 O/Ω/Θ 的来历&lt;/h3&gt;
&lt;p&gt;卷 1 第一章的数学部分（归纳法、数、幂与对数、和与积、排列、斐波那契、生成函数）常被读者跳过，但里面埋着全书的方法论核心：&lt;strong&gt;渐近分析（asymptotic analysis）&lt;/strong&gt;。几个史实值得澄清：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大 O 记号不是 Knuth 发明的——它来自数论学家 &lt;strong&gt;Bachmann&lt;/strong&gt;（1894 年），经 Landau 推广；&lt;/li&gt;
&lt;li&gt;Knuth 的贡献是把它引入算法分析，并在 1976 年专门写了一篇短文《Big Omicron and Big Omega and Big Theta》，&lt;strong&gt;推广了大 Ω（下界）和大 Θ（紧界）记号&lt;/strong&gt;，结束了当时文献里&amp;quot;什么都叫 O&amp;quot;的混乱局面。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说，今天我们写在面试白板上的 O(n log n) 这套语言，其语法规范是这套书（及配套论文）定下来的。Knuth 的态度始终如一：&lt;strong&gt;&amp;ldquo;大约 n 的平方量级&amp;quot;不是分析，&amp;ldquo;3n² + 5n - 7 次 MIX 指令执行&amp;quot;才是分析，O 记号是对前者的严格速写，不是含糊的挡箭牌。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;数据结构栈队列链表与树&#34;&gt;数据结构：栈、队列、链表与树&lt;/h3&gt;
&lt;p&gt;卷 1 第二章是整部书对后世影响最深的部分之一——今天教科书里的数据结构章节目录，几乎就是这一章的子孙：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;线性结构&lt;/strong&gt;：栈、队列、双端队列，以及链表（含循环链表、双向链表）的完整代数化描述——插入、删除、遍历的每一步都用 MIX 实现并计算代价。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;树与二叉树&lt;/strong&gt;：形式化定义、三种遍历（先序/中序/后序）、&lt;strong&gt;线索二叉树（threaded tree）&lt;/strong&gt;——利用空指针存放前驱后继信息，让遍历不再需要栈。这是一个漂亮的&amp;quot;空间复用&amp;quot;思想实验。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态存储分配与垃圾回收&lt;/strong&gt;：内存池的伙伴系统（buddy system）、首次适配/最佳适配策略、以及垃圾回收的标记思想——1968 年就成体系地写在书里，比多数编程语言拥有 GC 早了一代人。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;感悟&lt;/strong&gt;：读这一章最大的震撼是&amp;quot;年代错位感&amp;rdquo;——我们以为的&amp;quot;现代概念&amp;rdquo;（垃圾回收、智能指针的引用计数思想、内存分配策略的权衡），全部写在 1968 年的书里，连权衡的框架都没变过。所谓新技术，多数是老思想在新硬件上的重排。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三卷-2半数值算法随机数与算得准的艺术&#34;&gt;三、卷 2《半数值算法》：随机数与&amp;quot;算得准&amp;quot;的艺术&lt;/h2&gt;
&lt;p&gt;卷 2 处理一个独特的中间地带：对象是数，但关心的是算法而非数值分析。两大主线是随机数和算术。&lt;/p&gt;
&lt;p&gt;先解释一下这个奇怪的书名：&lt;strong&gt;&amp;ldquo;半数值&amp;rdquo;（seminumerical）&lt;/strong&gt; 指的是这类算法介于&amp;quot;纯数值计算&amp;quot;（数值分析的地盘，关心连续数学与误差界）和&amp;quot;纯符号处理&amp;quot;（编译、树操作的地盘）之间——输入输出是数，但算法的骨架是离散的组合结构。随机数生成、进制转换、多精度算术都属于这一带。&lt;/p&gt;
&lt;h3 id=&#34;随机数不该用随机的方法生成&#34;&gt;随机数：不该用随机的方法生成&lt;/h3&gt;
&lt;p&gt;卷 2 第三章是全书被引用最多的章节之一，开篇那句名言每个工程师都该见过一次：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Random numbers should not be generated by a method chosen at random.&amp;quot;（随机数不该用一个随机选出来的方法生成。）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Knuth 用亲身经历佐证这句话：他年轻时曾设计过一个&amp;quot;超级随机&amp;quot;的生成器——程序里随机地跳转、随机地执行不同操作，自以为复杂到不可能有规律；实际一跑，&lt;strong&gt;序列几乎立刻陷入一个短循环或不动点&lt;/strong&gt;。教训被写成定理级别的警告：复杂性不等于随机性，没有理论分析的&amp;quot;看起来乱&amp;quot;都是自欺欺人。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;线性同余法（LCG）&lt;/strong&gt;：x 的下一个值 = (a·x + c) mod m。全书用几十页分析三个参数怎么选——模数 m、乘数 a、增量 c 的选择决定了周期长度和统计质量，每一个坏选择的下场都有具体展示。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;统计检验&lt;/strong&gt;：卡方检验、Kolmogorov-Smirnov 检验、以及专门测高维均匀性的&lt;strong&gt;谱检验（spectral test）&lt;/strong&gt;——一个 LCG 可以在一维上完美均匀，在二维平面上却排成几条明显的直线，谱检验就是抓这种&amp;quot;隐藏结构&amp;quot;的。&lt;/li&gt;
&lt;li&gt;这一章的工程翻译到今天依然直接：&lt;strong&gt;不要用 &lt;code&gt;rand()&lt;/code&gt; 做密码学，不要自己发明随机数生成器，用之前先查它的检验记录。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;高精度算术与算得准&#34;&gt;高精度算术与&amp;quot;算得准&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;另一条主线是让计算机突破机器字长地算数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多精度算术&lt;/strong&gt;：加减乘的经典算法之外，重点是&lt;strong&gt;算法 D（多精度除法）&lt;/strong&gt;——除法是四则运算里唯一需要&amp;quot;试商&amp;quot;的，Knuth 给出完整的规范化、试商、校正流程和正确性证明。今天所有大整数库的除法实现，祖师爷都是这一节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;进制转换&lt;/strong&gt;：二进制、十进制之间的转换算法及其代价分析——这个在当年是日常刚需。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有理数与浮点运算&lt;/strong&gt;：浮点数的表示、舍入误差分析——&amp;ldquo;浮点算术不是实数算术&amp;quot;这个每个工程师都会踩的坑，书里有完整的误差传播分析。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多项式算术与幂的快速计算&lt;/strong&gt;：包括快速幂（平方-乘方法）的前身分析，以及乘法复杂度的下潜——Karatsuba 乘法这类&amp;quot;比课本算法快&amp;quot;的分治思路。更进一步是**加法链（addition chain）**问题：计算 x 的 n 次方最少需要几次乘法？&amp;ldquo;反复平方&amp;quot;并不总是最优，而求最优加法链本身至今没有完全解决——又一个&amp;quot;看似简单、实则研究级&amp;quot;的 50 分题栖息地。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;感悟&lt;/strong&gt;：卷 2 是四卷里&amp;quot;最数学&amp;quot;的一卷，但它的工程含义一点不虚：凡是钱、坐标、时间戳参与计算的地方，都在和&amp;quot;算得准&amp;quot;打交道。浮点误差、大数溢出、随机数质量——这三类生产事故的完整理论都在这一卷里，早该被列为后端工程师的体检项目。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四卷-3排序与查找工程师的硬通货&#34;&gt;四、卷 3《排序与查找》：工程师的硬通货&lt;/h2&gt;
&lt;p&gt;四卷里工程密度最高、最值得当工具书常备的一卷。Knuth 把排序和查找这两个&amp;quot;最古老的生产问题&amp;quot;做到了考古学级别的穷尽。&lt;/p&gt;
&lt;h3 id=&#34;内排序一个家族的谱系&#34;&gt;内排序：一个家族的谱系&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    S[&amp;#34;内排序算法家族&amp;#34;] --&amp;gt; I[&amp;#34;插入类&amp;lt;br/&amp;gt;直接插入 / Shell 排序&amp;#34;]
    S --&amp;gt; E[&amp;#34;交换类&amp;lt;br/&amp;gt;冒泡 / 快速排序 Hoare 1962&amp;#34;]
    S --&amp;gt; SE[&amp;#34;选择类&amp;lt;br/&amp;gt;直接选择 / 堆排序 Williams-Floyd&amp;#34;]
    S --&amp;gt; M[&amp;#34;归并类&amp;lt;br/&amp;gt;二路归并 / 自然归并&amp;#34;]
    S --&amp;gt; D[&amp;#34;分布类&amp;lt;br/&amp;gt;计数 / 基数排序&amp;#34;]
    E -.-&amp;gt;|&amp;#34;平均最优&amp;lt;br/&amp;gt;原地性差&amp;#34;| NOTE[&amp;#34;各有适用场景&amp;lt;br/&amp;gt;没有全能冠军&amp;#34;]
    M -.-&amp;gt;|&amp;#34;稳定 + 可外排&amp;#34;| NOTE
    style NOTE fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;书里对每一类的处理都是&amp;quot;描述 + 实现 + 精确分析&amp;quot;三段式，几个今天仍在生产环境活跃的名字：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;快速排序&lt;/strong&gt;（Hoare，1962）：Knuth 给出了平均比较次数的完整推导，以及最坏 O(n²) 的触发条件——&amp;ldquo;已排序输入配最左基准元&amp;quot;这个教科书反面案例就出自这里的分析。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;堆排序&lt;/strong&gt;（Williams 提出堆，Floyd 改进）：最坏情况也是 O(n log n)，堆这个数据结构本身后来长成了优先级队列的标准实现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;归并排序&lt;/strong&gt;：稳定、可预测，并且是通往外排序的桥。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;读这一章时建议始终带着 Knuth 的三个评价维度去看每个算法：&lt;strong&gt;稳定性&lt;/strong&gt;（相等元素的相对次序是否保持）、&lt;strong&gt;原地性&lt;/strong&gt;（额外空间是常数还是随 n 增长）、&lt;strong&gt;适应性&lt;/strong&gt;（输入已接近有序时能否变快）。三个维度没有全能冠军——快排快在常数、堆排赢在最坏情况、归并赢在稳定和可外排——&lt;strong&gt;选型就是在这张三维表里做取舍&lt;/strong&gt;，这也是&amp;quot;没有银弹，只有权衡&amp;quot;在算法层的具体形态。&lt;/p&gt;
&lt;h3 id=&#34;最优排序n-log-n-下界的信息论论证&#34;&gt;最优排序：n log n 下界的信息论论证&lt;/h3&gt;
&lt;p&gt;卷 3 最优雅的一段数学是&lt;strong&gt;基于比较的排序的下界证明&lt;/strong&gt;，值得单独记：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[&amp;#34;n 个元素&amp;lt;br/&amp;gt;共有 n! 种可能排列&amp;#34;] --&amp;gt; B[&amp;#34;比较排序 = 决策树&amp;lt;br/&amp;gt;每个内部节点是一次比较&amp;lt;br/&amp;gt;每片叶子对应一种排列&amp;#34;]
    B --&amp;gt; C[&amp;#34;树至少有 n! 片叶子&amp;#34;]
    C --&amp;gt; D[&amp;#34;高度至少为 log2(n!)&amp;#34;]
    D --&amp;gt; E[&amp;#34;Stirling 公式&amp;lt;br/&amp;gt;log2(n!) 约等于&amp;lt;br/&amp;gt;n log2 n - 1.44n&amp;#34;]
    E --&amp;gt; F[&amp;#34;结论:&amp;lt;br/&amp;gt;任何比较排序的最坏情况&amp;lt;br/&amp;gt;下界为 Ω(n log n)&amp;#34;]
    style F fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;这个论证的力量在于它&lt;strong&gt;不针对任何具体算法&lt;/strong&gt;——它限制的是&amp;quot;比较&amp;quot;这个信息获取方式本身：一次比较最多带来 1 比特信息，而区分 n! 种排列需要 log2(n!) 比特。要快过 n log n，唯一的出路是放弃纯比较——这正是基数排序、计数排序这些&amp;quot;分布类&amp;quot;算法存在的理由。这是我在全书中最喜欢的一段：&lt;strong&gt;用信息论给一类算法封顶，一句话堵死一个方向的无效努力。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;外排序与查找&#34;&gt;外排序与查找&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;外排序&lt;/strong&gt;：当数据放不进内存，瓶颈从比较次数变成读写趟数。多路归并、**置换选择（replacement selection）**生成初始归并段、多相归并——这一整套是磁带时代的遗产，但思想直接活在今天的 LSM-tree（LevelDB/RocksDB 的多路归并 compaction）里。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查找&lt;/strong&gt;：顺序查找与&lt;strong&gt;二分查找&lt;/strong&gt;（Knuth 照例指出：思路人人会，写对的没几个——边界条件的完整分析在书里；他还考据出二分查找的思路 1946 年就见诸文献，而第一个对所有输入规模都正确的完整算法直到 1962 年才发表，一个&amp;quot;显而易见&amp;quot;的算法花了十六年才写对）；&lt;strong&gt;哈希&lt;/strong&gt;：拉链法、开放寻址、线性探测的平均探查次数分析——线性探测的完整数学分析正是 Knuth 本人在 1962 年做出的，他自称正是这个问题让他决定写这套书；&lt;strong&gt;平衡树&lt;/strong&gt;：AVL 树的旋转与再平衡，多路查找树与 &lt;strong&gt;B 树&lt;/strong&gt;——数据库索引的物理形态；&lt;strong&gt;数字查找树（trie）&lt;/strong&gt;：按位/按字符逐级展开的查找结构。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五卷-4a组合算法生成一切的艺术&#34;&gt;五、卷 4A《组合算法》：生成一切的艺术&lt;/h2&gt;
&lt;p&gt;隔了 38 年，2011 年出的卷 4A 换了一个世界：从&amp;quot;算数&amp;quot;和&amp;quot;排序&amp;quot;进入&lt;strong&gt;组合对象&lt;/strong&gt;——布尔函数、组合、排列、划分——的领域。这卷的气质和前三卷一脉相承：先把对象定义到无歧义，再讨论&amp;quot;如何系统性地、不重不漏地枚举出全部实例&amp;rdquo;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;布尔函数与按位运算&lt;/strong&gt;（7.1 节）：真值表、按位技巧的宝库——掩码、并行按位计数（population count 的 sideways addition）、&amp;ldquo;x 与 x-1 的按位与可以抹掉最低位的 1&amp;quot;这类惯用法——这一节读起来像高级位操作黑魔法集，但每个技巧都有正确性论证。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成所有组合对象&lt;/strong&gt;（7.2.1 节）：全 n 元组与 &lt;strong&gt;Gray 码&lt;/strong&gt;（相邻码字只差一位的编码，枚举时每次只翻转一位）、全排列、全组合、整数划分、集合划分、所有树——每类对象都给出&amp;quot;不重不漏、常数均摊时间&amp;quot;的生成算法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回溯思想&lt;/strong&gt;：组合生成的算法骨子里都是&amp;quot;受控的回溯&amp;rdquo;——按字典序推进、到头回退。系统化的回溯框架（Algorithm B）在卷 4B 的 7.2.2 节正式登场；顺带交代一句出版史：4A 出版后 Knuth 继续以分册形式推进，卷 4B 已于 2022 年正式成书，当年那个&amp;quot;卷 4 写了四十年&amp;quot;的段子至此翻篇了一半。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用一张图记住回溯的骨架——所有组合枚举问题都可以投影成同一棵树：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    R[&amp;#34;空解&amp;lt;br/&amp;gt;第 0 层&amp;#34;] --&amp;gt; A[&amp;#34;第 1 位选 a&amp;#34;]
    R --&amp;gt; B[&amp;#34;第 1 位选 b&amp;#34;]
    A --&amp;gt; A1[&amp;#34;第 2 位选 a&amp;lt;br/&amp;gt;...继续深入&amp;#34;]
    A --&amp;gt; A2[&amp;#34;第 2 位选 b&amp;#34;]
    A2 --&amp;gt;|&amp;#34;约束不满足&amp;lt;br/&amp;gt;剪枝回退&amp;#34;| X1[&amp;#34;放弃整棵子树&amp;#34;]
    A1 --&amp;gt; A1L[&amp;#34;到达叶子&amp;lt;br/&amp;gt;输出一个完整解&amp;#34;]
    B --&amp;gt; B1[&amp;#34;...同样的展开&amp;#34;]
    X1 -.-&amp;gt;|&amp;#34;回退到最近分叉&amp;lt;br/&amp;gt;试下一个分支&amp;#34;| A
    style X1 fill:#ffcccc
    style A1L fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;核心纪律只有两条：&lt;strong&gt;到底就输出，碰壁就回退，回退后试下一个未试过的分支&lt;/strong&gt;——不重不漏靠的就是这条纪律，而不是事后去重。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;感悟&lt;/strong&gt;：卷 4A 对今天的工程师有一个直接映射：&lt;strong&gt;所有&amp;quot;遍历所有可能配置&amp;quot;的需求&lt;/strong&gt;——测试用例生成、组合优化、穷举校验——都是组合生成问题，而&amp;quot;生成&amp;quot;远比&amp;quot;收集后再去重&amp;quot;高效。不重不漏四个字，说起来像小学要求，做起来是算法设计里最硬的纪律之一。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六怎么读这套书习题分级费马大定理与路线图&#34;&gt;六、怎么读这套书：习题分级、费马大定理与路线图&lt;/h2&gt;
&lt;h3 id=&#34;习题分级体系00-到-50-的登山标尺&#34;&gt;习题分级体系：00 到 50 的登山标尺&lt;/h3&gt;
&lt;p&gt;TAOCP 的习题是半本书——Knuth 给每道题标了难度分，这套编号体系本身就是个值得单独记住的设计：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;编号&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
					&lt;th&gt;预期投入&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;00&lt;/td&gt;
					&lt;td&gt;看一眼就该会&lt;/td&gt;
					&lt;td&gt;几秒钟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10&lt;/td&gt;
					&lt;td&gt;简单&lt;/td&gt;
					&lt;td&gt;一分钟内&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;20&lt;/td&gt;
					&lt;td&gt;中等&lt;/td&gt;
					&lt;td&gt;一刻钟上下&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;30&lt;/td&gt;
					&lt;td&gt;较难&lt;/td&gt;
					&lt;td&gt;可能需要数小时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;40&lt;/td&gt;
					&lt;td&gt;学期项目级&lt;/td&gt;
					&lt;td&gt;数周&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;50&lt;/td&gt;
					&lt;td&gt;研究级问题&lt;/td&gt;
					&lt;td&gt;出题时可能无人解决&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;编号前可加 M（数学向）或 HM（高等数学向）。最著名的梗是卷 1 里那道 &lt;strong&gt;[M50]&lt;/strong&gt;：题目是&amp;quot;证明费马大定理&amp;rdquo;——Knuth 的意思是&amp;quot;这道题出题时没人会做&amp;rdquo;。1995 年 Wiles 真的证明了它之后，后续印次里这道题的处境变成了书迷间的段子。&lt;strong&gt;50 分题不是作业，是路标：它告诉你学科边界在哪里。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;我的路线图建议&#34;&gt;我的路线图建议&lt;/h3&gt;
&lt;p&gt;对全职工程师，&amp;ldquo;通读&amp;quot;是个伪目标，务实的姿势是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;卷 3 当工具书常备&lt;/strong&gt;：排序和查找是唯一一卷会在日常代码评审、性能分析、系统设计面试中直接变现的。通读一遍，之后按需回查。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卷 1 读第二章&lt;/strong&gt;：数据结构部分是&amp;quot;为什么链表这样设计、为什么 GC 这样工作&amp;quot;的第一性原理来源；第一章数学基础按需查，不必顺序啃。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卷 2 按需精读&lt;/strong&gt;：写大数、随机、浮点相关代码之前，把对应章节当 pre-mortem 读一遍。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卷 4A 当兴趣读物&lt;/strong&gt;：遇到组合枚举需求（生成测试组合、配置穷举）时按目录取用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;习题只做 20 分以下的&lt;/strong&gt;：10-20 分题保证理解，30 分以上当文献指南——题目本身常附带一整段文献史，不打算做题也值得读题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;别按顺序读&lt;/strong&gt;。Knuth 自己也没指望人顺序读：每节相对独立，前置依赖写在节首。把这套书当成&amp;quot;算法领域的百科全书&amp;quot;而不是&amp;quot;课程&amp;rdquo;，是心态上最重要的一步。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七落到工程实践这套书改变了什么&#34;&gt;七、落到工程实践：这套书改变了什么&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;复杂度分析从&amp;quot;感觉&amp;quot;变成了&amp;quot;账&amp;quot;。&lt;/strong&gt; 读过 Knuth 的分析后，再说&amp;quot;这个操作是 O(n)&amp;ldquo;会本能地问：常数是什么？最坏情况和平均情况分别是多少？输入分布假设是什么？这套书最宝贵的遗产不是任何单个算法，而是**&amp;ldquo;性能是可以、也必须被精确计算的&amp;quot;这个信念**——profile 之前的估算、capacity planning 里的量级推演，全是它的日常形态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对&amp;quot;下界&amp;quot;的敬畏。&lt;/strong&gt; n log n 的信息论论证训练了一种思维方式：优化之前先问这个问题的理论下界在哪，离下界还有多远。很多&amp;quot;再优化一下&amp;quot;的努力，看一眼下界就知道是徒劳——&lt;strong&gt;知道哪里没有油水，和知道哪里有油水一样值钱。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;随机与浮点有了红线意识。&lt;/strong&gt; &amp;ldquo;不自己造随机数生成器&amp;quot;&amp;ldquo;钱不用浮点表示&amp;quot;这类团队规约，以前是被当经验口诀背下来的；读完卷 2 它们变成了有证明的结论，执行的腰杆完全不一样。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;读旧文献的胆子变大了。&lt;/strong&gt; Knuth 的行文示范了一件事：1960 年代的论文不是&amp;quot;过时的古董&amp;rdquo;，而是很多问题唯一的完整答案所在。排障和选型时敢往回翻原始论文，是这套书给的胆量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对&amp;quot;正确性&amp;quot;的标准被永久抬高了。&lt;/strong&gt; 书里每个算法都带正确性证明或严格论证，读多了会形成一种肌肉记忆：写完一段非平凡逻辑，先问&amp;quot;循环不变式是什么&amp;quot;&amp;ldquo;边界情况枚举全了吗&amp;rdquo;。二分查找十六年才写对的考据，是这条标准最好的反面教材。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;本篇小结&#34;&gt;本篇小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;TAOCP 是算法学科的编年史加分析法典：七卷规划，卷 1-3 出版于 1968-1973，卷 4A 迟至 2011，副产品是 TeX；Gates 那句&amp;quot;读完发简历&amp;quot;说的是它的密度。&lt;/li&gt;
&lt;li&gt;MIX/MMIX 假想机不是老派怪癖，是方法论：要精确算性能账，就得有一台指令级确定的机器。&lt;/li&gt;
&lt;li&gt;卷 1 立规矩：算法五特征（有穷、确切、输入、输出、能行），数据结构大全，O/Ω/Θ 的语法规范（O 来自 Bachmann，Ω/Θ 由 Knuth 推广）。&lt;/li&gt;
&lt;li&gt;卷 2 管&amp;quot;算得准&amp;rdquo;：随机数不该用随机方法生成（LCG 参数分析、谱检验），多精度算术（算法 D），浮点误差。&lt;/li&gt;
&lt;li&gt;卷 3 是工程师硬通货：排序家族全谱、n log n 下界的信息论论证（比较即信息获取）、外排序思想活在今天的 LSM-tree 里、哈希与 B 树。&lt;/li&gt;
&lt;li&gt;卷 4A 进入组合世界：按位技巧、不重不漏地生成所有组合/排列/划分，回溯的思想雏形。&lt;/li&gt;
&lt;li&gt;读法：卷 3 常备、卷 1 读数据结构、卷 2/4A 按需精读；习题分级 00-50，[M50] 的费马大定理题是学科边界的路标。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这套书我没读完，大概率也永远不会读完——但这不妨碍它一直在工作：它就立在手边，像一个不说话的考官，每次想偷懒说&amp;quot;差不多 n log n 吧&amp;quot;的时候，抬头就能看见。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Donald E. Knuth, &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 1: &lt;em&gt;Fundamental Algorithms&lt;/em&gt; (3rd ed., Addison-Wesley, 1997; 初版 1968).&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 2: &lt;em&gt;Seminumerical Algorithms&lt;/em&gt; (3rd ed., 1997; 初版 1969).&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 3: &lt;em&gt;Sorting and Searching&lt;/em&gt; (2nd ed., 1998; 初版 1973).&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 4A: &lt;em&gt;Combinatorial Algorithms, Part 1&lt;/em&gt; (Addison-Wesley, 2011).&lt;/li&gt;
&lt;li&gt;Donald E. Knuth, &amp;ldquo;Big Omicron and Big Omega and Big Theta&amp;rdquo;, &lt;em&gt;ACM SIGACT News&lt;/em&gt;, 1976（O/Ω/Θ 记号规范化的原始短文）。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
