考虑 Fibonacci 数列,
F(n)=F(n−1)+F(n−2) 将右边两项看做是一个列向量的形式,令 Xn−1={Fn−1Fn−2} 很容易得到 Xn 的形式,即 Xn={FnFn−1} 现在的任务就是找到一个系数矩阵 A ,使得AXn−1=Xn,且 A 需与n无关。 如果能够找到这个 A ,则易知An−1X1=Xn,于是可以利用矩阵快速幂计算出 Xn 。这样就可以在 O(logn) 的时间内计算出指定的 Fibonacci 数。 这个矩阵很容易找,观察易得 A={1110}(1)推广一下,如果令 Fn=aFn−1+bFn−2 ,则系数矩阵为
A={a1b0}(2)Fibonacci 数列只是最简单的例子,对于稍微复杂一点的例子,二项式展开是常用的一项技术。 考虑计算:
Sn=∑i=1nik 易得 Sn=nk+Sn−1 如果仿照 Fibonacci 数列,令 Xn−1={nkSn−1} 则 Xn={(n+1)kSn} 此时,可求出 A=⎧⎩⎨⎪⎪(n+1n)k101⎫⎭⎬⎪⎪ 这个系数矩阵很明显是不能用的,因为它与 n 有关,无法将递推公式转化为矩阵的幂运算。 这里需要使用二项式展开。 Sn=(n−1+1)k+Sn−1=C0k(n−1)k+C1k(n−1)k−1+⋯+Ckk+Sn−1 此时,如果令 Xn−1=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(n−1)k(n−1)k−1⋮(n−1)0Sn−1⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ 则有 Xn=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪nknk−1⋮n0Sn⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ 现在的任务与刚才一样,找到一个系数矩阵 A ,使得AXn−1=Xn,且 A 需与n无关。 有关 Sn 的递推公式实际上就指明了 A 的最后一行。而利用二项式展开很容易得到其他行。 有 A=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪C0k0⋮0C0kC1kC0k−1⋮⋯C1k⋯⋯⋱⋯⋯CkkCk−1k−1⋮C00Ckk00⋮01⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(3) 最后有 An−1X1=Xn 且 X1={1 1 ⋯ 1}T 利用该系数矩阵可以在 O(k3logn) 时间内计算出 k 次方的和。再考虑一个一般情况:Sn=∑i=1n(ai+b)k 与刚才几乎一模一样,有 Sn=[a(n−1)+(a+b)]k+Sn−1=C0kak(n−1)k+C1kak−1(a+b)(n−1)k−1+⋯+Ckk(a+b)k+Sn−1 剩下的步骤,也几乎完全与之前的一样,令 Xn−1=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(n−1)k(n−1)k−1⋮(n−1)0Sn−1⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ 则 Xn=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪nknk−1⋮n0Sn⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ 同样,有关 Sn 的递推公式实际上就指明了 A 的最后一行,其他行则利用二项式展开得到。 有 A=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪C0k0⋮0C0kakC1kC0k−1⋮⋯C1kak−1(a+b)⋯⋯⋱⋯⋯CkkCk−1k−1⋮C00Ckk(a+b)k00⋮01⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(4)
假设要计算如下和式:
Sn=∑i=1nikki 同样,将其写成递推公式,有 Sn=nkkn+Sn−1=(n−1+1)kk(n−1)+1+Sn−1=C0k(n−1)kk(n−1)+1+C1k(n−1)k−1k(n−1)+1+⋯+Ckkk(n−1)+1+Sn−1 将与 n 有关的项抽出来作为列向量,令 Xn−1=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(n−1)kk(n−1)+1(n−1)k−1k(n−1)+1⋮(n−1)0k(n−1)+1Sn−1⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ 则 Xn=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪nkkn+1nk−1kn+1⋮n0kn+1Sn⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪同样,有关 Sn 的递推公式说明了系数矩阵 A 的最后一行。而其他行仍然可以由二项式展开得到,只是相差了一个系数k而已,这很容易解决。 最后,有
A=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪kC0k0⋮0C0kkC1kkC0k−1⋮⋯C1k⋯⋯⋱⋯⋯kCkkkCk−1k−1⋮kC00Ckk00⋮01⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(5)POJ3070利用了矩阵1,hdu3369利用了矩阵3和4,hdu3483利用了矩阵5。
