1. 整數裂項概述
1.1 1 * 2 + 2 * 3 + 3 * 4 + ... + (n - 1) * n = ?
解: 裂項公式為:
(n - 1) * n = [(n - 1) * n * (n + 1) - (n - 2) * (n - 1) * n] / 3
求解過程如下圖所示:
1.2 1 * 2 * 3 + 2 * 3 * 4 + 3 * 4 * 5 + ... + (n - 2) * (n - 1) * n = ?
解: 裂項公式為:
(n - 2) * (n - 1) * n = [(n - 2) * (n - 1) * n * (n + 2) - (n - 3) * (n - 2) * (n - 1) * n] / 4
求解過程如下圖所示:
1.3 1 * 3 + 3 * 5 + 5 * 7 + ... + 19 * 21 = ?
解: 注意在每個加數的兩個因數中,公差為2。求解過程如下圖所示:
1.4 5 * 10 * 15 + 10 * 15 * 20 + ... + 40 * 45 *50 = ?
解: 注意在每個加數的三個因數中,公差為5。求解過程如下圖所示:
2. 關於1**2 + 2**2 + 3**2 + ... + n**2 = n * (n + 1) * (2n +1) / 6的證明
證明的要點為:
n ** 2 = n ** 2 - 1 + 1 = n ** 2 - 1 ** 2 + 1 = (n - 1) * (n + 1) + 1
證明過程如下圖所示:
3. 關於1 * 2 * 3 * 4 + 3 * 4 * 5 * 6 + 5 * 6 * 7 * 8 + ... + 97 * 98 * 99 * 100 = ?的求解
這類問題的求解比前面的問題要復雜得多,因為兩個相鄰加數中,因數不滿足可直接裂項的連續性,即:
1 * 2 * 3 * 4 + 2 * 3 * 4 * 5
是滿足可直接裂項的連續性的,但是
1 * 2 * 3 * 4 + 3 * 4 * 5 * 6
並不滿足可直接裂項的連續性。怎么辦?
典型思路就是:構造滿足可直接裂項的連續性的序列,然后通過解方程組間接求解。
在未求解之前,我們先用一個很硬核的求解程序(暴力累加),看看結果是什么。
3.1 硬核求解程序
- foo.py (算法簡單粗暴)
1 #!/usr/bin/python3 2 """ Question: 3 1 * 2 * 3 * 4 + 4 3 * 4 * 5 * 6 + 5 5 * 6 * 7 * 8 + 6 ... + 7 97 * 98 * 99 * 100 8 = 9 4! 6! 8! 100! 10 ---- + ---- + ---- + ... + ----- 11 0! 2! 4! 96! 12 = ? 13 """ 14 import sys 15 16 17 def main(argc, argv): 18 if argc < 2: 19 print("Usage: %s <N> [-D]" % argv[0], file=sys.stderr) 20 print("e.g.", file=sys.stderr) 21 print(" %s 96" % argv[0], file=sys.stderr) 22 print(" %s 96 -D" % argv[0], file=sys.stderr) 23 return 1 24 25 n = int(argv[1]) 26 if argc == 3 and argv[2] == '-D': 27 debug = True 28 else: 29 debug = False 30 31 a = [] 32 i = 0 33 s = 0 34 while i <= n: 35 x = (i + 1) * (i + 2) * (i + 3) * (i + 4) 36 a.append('%d * %d * %d * %d' % (i + 1, i + 2, i + 3, i + 4)) 37 s += x 38 i += 2 39 if debug: 40 print('%s = %d' % (' + '.join(a), s)) 41 else: 42 b = [a[0], a[1], a[2], '...', a[-1]] 43 print('%s = %d' % (' + '.join(b), s)) 44 45 return 0 46 47 48 if __name__ == '__main__': 49 sys.exit(main(len(sys.argv), sys.argv))
- 運行foo.py
huanli@idorax16:~$ ./foo.py 96 -D 1 * 2 * 3 * 4 + 3 * 4 * 5 * 6 + 5 * 6 * 7 * 8 + 7 * 8 * 9 * 10 + 9 * 10 * 11 * 12 + 11 * 12 * 13 * 14 + 13 * 14 * 15 * 16 + 15 * 16 * 17 * 18 + 17 * 18 * 19 * 20 + 19 * 20 * 21 * 22 + 21 * 22 * 23 * 24 + 23 * 24 * 25 * 26 + 25 * 26 * 27 * 28 + 27 * 28 * 29 * 30 + 29 * 30 * 31 * 32 + 31 * 32 * 33 * 34 + 33 * 34 * 35 * 36 + 35 * 36 * 37 * 38 + 37 * 38 * 39 * 40 + 39 * 40 * 41 * 42 + 41 * 42 * 43 * 44 + 43 * 44 * 45 * 46 + 45 * 46 * 47 * 48 + 47 * 48 * 49 * 50 + 49 * 50 * 51 * 52 + 51 * 52 * 53 * 54 + 53 * 54 * 55 * 56 + 55 * 56 * 57 * 58 + 57 * 58 * 59 * 60 + 59 * 60 * 61 * 62 + 61 * 62 * 63 * 64 + 63 * 64 * 65 * 66 + 65 * 66 * 67 * 68 + 67 * 68 * 69 * 70 + 69 * 70 * 71 * 72 + 71 * 72 * 73 * 74 + 73 * 74 * 75 * 76 + 75 * 76 * 77 * 78 + 77 * 78 * 79 * 80 + 79 * 80 * 81 * 82 + 81 * 82 * 83 * 84 + 83 * 84 * 85 * 86 + 85 * 86 * 87 * 88 + 87 * 88 * 89 * 90 + 89 * 90 * 91 * 92 + 91 * 92 * 93 * 94 + 93 * 94 * 95 * 96 + 95 * 96 * 97 * 98 + 97 * 98 * 99 * 100 = 974510040 huanli@idorax16:~$ ./foo.py 96 1 * 2 * 3 * 4 + 3 * 4 * 5 * 6 + 5 * 6 * 7 * 8 + ... + 97 * 98 * 99 * 100 = 974510040
在正式求解此問題之前,先來個簡單一點的問題。例如:
1 * 2 + 3 * 4 + 5 * 6 + ... + 99 * 100 = ?
3.2 關於1 * 2 + 3 * 4 + 5 * 6 + ... + 99 * 100 = ?的求解
- 用Python代碼求解結果如下:
>>> s = 0 >>> i = 1 >>> while i <= 99: ... x = i * (i + 1) ... s += x ... i += 2 ... >>> s 169150
- 基於整數裂項+構造方程組的求解過程如下:
3.3 關於1 * 2 * 3 * 4 + 3 * 4 * 5 * 6 + 5 * 6 * 7 * 8 + ... + 97 * 98 * 99 * 100 = ?的求解
本題為小學六年級奧數題,題目難度比較大,至少對小學六年級學生來說很有挑戰性。有了3.2的基礎,接下來的求解思路就很清楚了,只是求解過程需要逐次降階而已。
求解過程如下所示:
在上述求解過程中,一共使用了整數裂項3次,解二元一次方程組3次。因為既包括整數裂項、等差數列求和和解方程組,故難度較大。
那么,如果做如下推廣,將如何?
a) 1 * 2 * 3 * 4 + 3 * 4 * 5 * 6 + 5 * 6 * 7 * 8 + ... + (2m-1)*(2m)*(2m+1)*(2m+2) = ?
b) 1 * 2 * 3 * 4 + 5 * 6 * 7 * 8 + 9 * 10 * 11 * 12 + ... + (4m+1)*(4m+2)*(4m+3)*(4m+4) = ?
4. 結束語
裂項求和是分解與組合思想在數列求和中的具體應用。其中,整數裂項求和,可直接解決諸如:
1 * 2 + 2 * 3 + 3 * 4 + ... + (n-1) * n = ? 1 * 2 * 3 + 2 * 3 * 4 + 3 * 4 * 5 + ... + (n-2) * (n-1) * n = ?
之類的問題,但無法直接解決
1 * 2 + 3 * 4 + 5 * 6 + ... + (2m - 1) * 2m = ?
之類的問題。后者之所以不能被直接解決,是因為不滿足可整數裂項的連續性。對這類問題的求解,不但借助了解方程組的思想,而且利用了逐級降階的方法,實為有趣。
更一般地,下面的問題可遞歸求解。
例如:
# n = m = 10, k = 9
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
+ 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20
+ 21 * 22 * 23 * 24 * 25 * 26 * 27 * 28 * 29 * 30
+ ...
+ 91 * 92 * 93 * 94 * 95 * 96 * 97 * 98 * 99 * 100
= ?
參考資料: