对应《具体数学:计算机科学基础(第 2 版)》第 2 章 §2.5,书内第 35---39 页。本文沿用专栏三级编号。
这一节用同一个问题比较多种解法:
Q n = ∑ k = 1 n k 2 , Q 0 = 0. Q_n=\sum_{k=1}^{n}k^2,\qquad Q_0=0. Qn=k=1∑nk2,Q0=0.
答案是
Q n = n ( n + 1 ) ( 2 n + 1 ) 6 . \boxed{Q_n=\frac{n(n+1)(2n+1)}6.} Qn=6n(n+1)(2n+1).
但这一节更值得学习的是:没有现成答案时可以从哪里入手,以及一种方法失效以后怎样调整。
1. 先做小规模检查,别把它当成证明
| n n n | 0 0 0 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
|---|---|---|---|---|---|---|
| Q n Q_n Qn | 0 0 0 | 1 1 1 | 5 5 5 | 14 14 14 | 30 30 30 | 55 55 55 |
这些值可以用来排除错误公式,但有限个样本不能证明一个公式对所有 n n n 成立。
原书把查找现有结果称为方法 0。查公式可以节省时间,但仍要核对求和范围与假设: ∑ k = 0 n − 1 k 2 \sum_{k=0}^{n-1}k^2 ∑k=0n−1k2 和 ∑ k = 1 n k 2 \sum_{k=1}^{n}k^2 ∑k=1nk2 的式子并不相同。我们也希望知道如何自己找到结果。
2. 猜测以后,用归纳法验证
设候选公式为 F ( n ) = n ( n + 1 ) ( 2 n + 1 ) / 6 F(n)=n(n+1)(2n+1)/6 F(n)=n(n+1)(2n+1)/6。它满足 F ( 0 ) = 0 F(0)=0 F(0)=0,并且
F ( n ) − F ( n − 1 ) = n ( ( n + 1 ) ( 2 n + 1 ) − ( n − 1 ) ( 2 n − 1 ) ) 6 = n 2 . \begin{aligned} F(n)-F(n-1) &=\frac{n\bigl((n+1)(2n+1)-(n-1)(2n-1)\bigr)}6\\ &=n^2. \end{aligned} F(n)−F(n−1)=6n((n+1)(2n+1)−(n−1)(2n−1))=n2.
这与 Q n − Q n − 1 = n 2 Q_n-Q_{n-1}=n^2 Qn−Qn−1=n2 相同,因此归纳法证明 F ( n ) = Q n F(n)=Q_n F(n)=Qn。
归纳法在这里负责确认答案。它并没有自动解释为什么应该先猜出一个三次多项式,更没有告诉我们如何猜中系数。发现与验证,是两件相关但不同的工作。
3. 扰动平方和失败,试着升高一次
直接比较平方和的首尾:
Q n + ( n + 1 ) 2 = ∑ k = 0 n ( k + 1 ) 2 . Q_n+(n+1)^2=\sum_{k=0}^{n}(k+1)^2. Qn+(n+1)2=k=0∑n(k+1)2.
右边展开以后又含有 Q n Q_n Qn,消掉两边的 Q n Q_n Qn,得到的是整数和公式,并不能求出平方和。
这次"失败"反而给了提示:若平移使幂次降低一阶,就从高一阶的幂开始。
利用
( k + 1 ) 3 − k 3 = 3 k 2 + 3 k + 1 , (k+1)^3-k^3=3k^2+3k+1, (k+1)3−k3=3k2+3k+1,
对 k = 0 , 1 , ... , n k=0,1,\ldots,n k=0,1,...,n 求和。左边叠缩,只留下 ( n + 1 ) 3 (n+1)^3 (n+1)3:
( n + 1 ) 3 = 3 Q n + 3 n ( n + 1 ) 2 + ( n + 1 ) . (n+1)^3=3Q_n+3\frac{n(n+1)}2+(n+1). (n+1)3=3Qn+32n(n+1)+(n+1).
于是
3 Q n = ( n + 1 ) 3 − 3 2 n ( n + 1 ) − ( n + 1 ) , 3Q_n=(n+1)^3-\frac32n(n+1)-(n+1), 3Qn=(n+1)3−23n(n+1)−(n+1),
整理便得到 Q n = n ( n + 1 ) ( 2 n + 1 ) / 6 Q_n=n(n+1)(2n+1)/6 Qn=n(n+1)(2n+1)/6。
这里没有先猜答案,而是通过立方差主动制造平方项。
4. 成套方法:把简单解作为一组工具
把前面的线性递归扩充为
R 0 = α , R n = R n − 1 + β + γ n + δ n 2 . R_0=\alpha,\qquad R_n=R_{n-1}+\beta+\gamma n+\delta n^2. R0=α,Rn=Rn−1+β+γn+δn2.
写成
R n = α A ( n ) + β B ( n ) + γ C ( n ) + δ D ( n ) . R_n=\alpha A(n)+\beta B(n)+\gamma C(n)+\delta D(n). Rn=αA(n)+βB(n)+γC(n)+δD(n).
前面已经知道
A ( n ) = 1 , B ( n ) = n , C ( n ) = n ( n + 1 ) 2 . A(n)=1,\quad B(n)=n,\quad C(n)=\frac{n(n+1)}2. A(n)=1,B(n)=n,C(n)=2n(n+1).
再取简单解 R n = n 3 R_n=n^3 Rn=n3。由于
n 3 − ( n − 1 ) 3 = 1 − 3 n + 3 n 2 , n^3-(n-1)^3=1-3n+3n^2, n3−(n−1)3=1−3n+3n2,
对应参数为 ( α , β , γ , δ ) = ( 0 , 1 , − 3 , 3 ) (\alpha,\beta,\gamma,\delta)=(0,1,-3,3) (α,β,γ,δ)=(0,1,−3,3),所以
n 3 = B ( n ) − 3 C ( n ) + 3 D ( n ) . n^3=B(n)-3C(n)+3D(n). n3=B(n)−3C(n)+3D(n).
这就确定了
D ( n ) = n 3 − n + 3 n ( n + 1 ) / 2 3 = n ( n + 1 ) ( 2 n + 1 ) 6 . D(n)=\frac{n^3-n+3n(n+1)/2}{3} =\frac{n(n+1)(2n+1)}6. D(n)=3n3−n+3n(n+1)/2=6n(n+1)(2n+1).
平方和对应参数 ( 0 , 0 , 0 , 1 ) (0,0,0,1) (0,0,0,1),故 Q n = D ( n ) Q_n=D(n) Qn=D(n)。比起为每个递归单独猜公式,成套方法把线性结构利用得更充分。
5. 积分先给主项,再精确处理误差
连续近似给出
∫ 0 n x 2 d x = n 3 3 . \int_0^n x^2\,dx=\frac{n^3}{3}. ∫0nx2dx=3n3.
但 Q n Q_n Qn 是一组矩形的面积和,不能直接等同于曲线下的面积。定义误差
E n = Q n − n 3 3 . E_n=Q_n-\frac{n^3}{3}. En=Qn−3n3.
相邻项之差为
E n − E n − 1 = n 2 − n 3 − ( n − 1 ) 3 3 = n − 1 3 . \begin{aligned} E_n-E_{n-1} &=n^2-\frac{n^3-(n-1)^3}{3}\\ &=n-\frac13. \end{aligned} En−En−1=n2−3n3−(n−1)3=n−31.
原来平方级别的增量变成了一次式。由 E 0 = 0 E_0=0 E0=0,得到
E n = n ( n + 1 ) 2 − n 3 = n 2 2 + n 6 . E_n=\frac{n(n+1)}2-\frac n3 =\frac{n^2}{2}+\frac n6. En=2n(n+1)−3n=2n2+6n.
所以
Q n = n 3 3 + n 2 2 + n 6 . Q_n=\frac{n^3}{3}+\frac{n^2}{2}+\frac n6. Qn=3n3+2n2+6n.
积分不只用于估数量级。一个好的近似,还可能让"剩下的误差"变成更容易精确求解的问题。
6. 展开成二重和,再换序收缩
把 k 2 k^2 k2 看成 k k k 个 k k k 相加:
Q n = ∑ k = 1 n ∑ j = 1 k k = ∑ j = 1 n ∑ k = j n k . Q_n=\sum_{k=1}^{n}\sum_{j=1}^{k}k =\sum_{j=1}^{n}\sum_{k=j}^{n}k. Qn=k=1∑nj=1∑kk=j=1∑nk=j∑nk.
令 T n = n ( n + 1 ) / 2 T_n=n(n+1)/2 Tn=n(n+1)/2。内和为 T n − T j − 1 T_n-T_{j-1} Tn−Tj−1,因此
Q n = n T n − ∑ j = 1 n j ( j − 1 ) 2 = n T n − Q n − T n 2 . \begin{aligned} Q_n&=nT_n-\sum_{j=1}^{n}\frac{j(j-1)}2\\ &=nT_n-\frac{Q_n-T_n}{2}. \end{aligned} Qn=nTn−j=1∑n2j(j−1)=nTn−2Qn−Tn.
移项得到
3 Q n = ( 2 n + 1 ) T n , 3Q_n=(2n+1)T_n, 3Qn=(2n+1)Tn,
答案再次出现。把一个求和号变成两个,表面上更复杂,却让等差和工具有了发挥的机会。中间表达式不必每一步都比前一步短。
7. 这些方法应该怎样选?
| 当前看到的结构 | 可以先尝试的办法 |
|---|---|
| 已有一个候选封闭形式 | 检查初始值和相邻差,再用归纳法证明 |
| 通项平移后结构相近 | 扰动;必要时换一个更高次的辅助和 |
| 递归对参数线性 | 成套方法,使用已知简单解 |
| 已知容易积分的近似 | 把主项减去,研究误差的增量 |
| 通项可以写成重复计数 | 展开成多重和,再交换求和次序 |
原书还列出方法 6"有限微积分"和方法 7"生成函数",并将具体展开留给下一节及后续章节。它们不是又两条需要死记的平方和证明,而是处理更大类问题的工具。
8. 程序验证与自测
python
from fractions import Fraction
def square_sum(n):
if n < 0:
raise ValueError("n 必须是非负整数")
return n * (n + 1) * (2 * n + 1) // 6
total = 0
for n in range(501):
total += n * n
assert total == square_sum(n)
error = Fraction(total) - Fraction(n ** 3, 3)
assert error == Fraction(n * n, 2) + Fraction(n, 6)
if n > 0:
assert square_sum(n) - square_sum(n - 1) == n * n
print(square_sum(20)) # 2870
为什么检查前 500 个值还不等于数学证明? 它仍然只检查了有限输入;一般性结论依靠前面的代数与归纳论证。
扰动平方和时未知量消掉了,下一步是什么? 看消去后留下了什么结构,再考虑从立方和或立方差入手。
n 3 / 3 n^3/3 n3/3 与平方和相差多少? 精确误差是 n 2 / 2 + n / 6 n^2/2+n/6 n2/2+n/6,而不是零。
参考:Ronald L. Graham、Donald E. Knuth、Oren Patashnik 著,张明尧、张凡译,《具体数学:计算机科学基础(第 2 版)》,人民邮电出版社,§2.5。本文按本节主题重新组织解释与推导,并补充程序核验;不是原文摘录。