根据递推公式构造系数矩阵用于快速幂

转载自: https://blog.csdn.net/u012061345/article/details/52224623

简单的例子

Fibonacci数列

考虑Fibonacci数列,  F(n)=F(n-1)+F(n-2)


将右边两项看做是一个列向量的形式,令 

 X_{n-1}=\left\{\begin{matrix}F_{n-1}\\F_{n-2}\end{matrix}\right\}


很容易得到Xn的形式,即 

X_{n}=\left\{\begin{matrix}F_{n}\\F_{n-1}\end{matrix}\right\}
现在的任务就是找到一个系数矩阵A,使得AX_{n-1}=X_nAXn−1=XnAXn−1=Xn,且A需与n无关。 
如果能够找到这个n,则易知A^{n-1}X_1=X_n,于是可以利用矩阵快速幂计算出Xn。这样就可以在O(logn)的时间内计算出指定的Fibonacci数。 
这个矩阵很容易找,观察易得 

A=\left\{\begin{matrix}1&1\\1& 0\end{matrix}\right\}\tag{1}

 

Fibonacci数列变种

推广一下,如果令F_n=aF_{n-1}+bF_{n-2},则系数矩阵为 

A=\left\{\begin{matrix}a&b\\1& 0\end{matrix}\right\}\tag{2}

 

利用二项式展开构造矩阵

计算k次方和

FibonacciFibonacci数列只是最简单的例子,对于稍微复杂一点的例子,二项式展开是常用的一项技术。 
考虑计算: 

S_n=\sum_{i=1}^n{i^k}


易得 

Sn=nk+Sn−1


如果仿照Fibonacci数列,令 

X_{n-1}=\left\{\begin{matrix}n^k\\S_{n-1}\end{matrix}\right\}


则 

X_{n}=\left\{\begin{matrix}(n+1)^k\\S_{n}\end{matrix}\right\}


此时,可求出 

A=\left\{\begin{matrix}\left({\frac{n+1}{n}}\right)^{k}&&0\\1&&1\end{matrix}\right\}


这个系数矩阵很明显是不能用的,因为它与nn有关,无法将递推公式转化为矩阵的幂运算。 
这里需要使用二项式展开。 

S_n=(n-1+1)^k+S_{n-1}\\=C_k^0(n-1)^k+C_k^1(n-1)^{k-1}+\cdots+C_k^k+S_{n-1}


此时,如果令 

X_{n-1}=\left\{\begin{matrix}(n-1)^k\\(n-1)^{k-1}\\\vdots\\(n-1)^0\\S_{n-1}\end{matrix}\right\}


则有 

X_{n}=\left\{\begin{matrix}n^k\\n^{k-1}\\\vdots\\n^0\\S_{n}\end{matrix}\right\}


现在的任务与刚才一样,找到一个系数矩阵A,使得AXn-1=Xn,且A需与n无关。 
有关SnSn的递推公式实际上就指明了AA的最后一行。而利用二项式展开很容易得到其他行。 
有 

A=\left\{\begin{matrix}C_k^0&&C_k^1&&\cdots&&C_k^k&&0\\0&&C_{k-1}^0&&\cdots&&C_{k-1}^{k-1}&&0\\\vdots&&\vdots&&\ddots&&\vdots&&\vdots\\0&&\cdots&&\cdots&&C_0^0&&0\\C_k^0&&C_k^1&&\cdots&&C_k^k&&1\end{matrix}\right\}\tag{3}
最后有 

A^{n-1}X_1=X_n


且 

X_1=\left\{1\space1\space\cdots\space1\right\}^T


利用该系数矩阵可以在O(k3logn)O(k3log⁡n)时间内计算出kk次方的和。

 

更一般的例子

再考虑一个一般情况:

S_n=\sum_{i=1}^n{(ai+b)^k}


与刚才几乎一模一样,有 

S_n=[a(n-1)+(a+b)]^k+S_{n-1}\\=C_k^0a^k(n-1)^k+C_k^1a^{k-1}(a+b)(n-1)^{k-1}+\cdots+C_k^k(a+b)^k+S_{n-1}


剩下的步骤,也几乎完全与之前的一样,令 

X_{n-1}=\left\{\begin{matrix}(n-1)^k\\(n-1)^{k-1}\\\vdots\\(n-1)^0\\S_{n-1}\end{matrix}\right\}


则 

X_{n}=\left\{\begin{matrix}n^k\\n^{k-1}\\\vdots\\n^0\\S_{n}\end{matrix}\right\}


同样,有关SnSn的递推公式实际上就指明了AA的最后一行,其他行则利用二项式展开得到。 
有 

A=\left\{\begin{matrix}C_k^0&&C_k^1&&\cdots&&C_k^k&&0\\0&&C_{k-1}^0&&\cdots&&C_{k-1}^{k-1}&&0\\\vdots&&\vdots&&\ddots&&\vdots&&\vdots\\0&&\cdots&&\cdots&&C_0^0&&0\\C_k^0a^k&&C_k^1a^{k-1}(a+b)&&\cdots&&C_k^k(a+b)^k&&1\end{matrix}\right\}\tag{4}

 

更复杂的例子

假设要计算如下和式: 

S_n=\sum_{i=1}^ni^kk^i


同样,将其写成递推公式,有 

S_n=n^kk^n+S_{n-1}\\=(n-1+1)^kk^{(n-1)+1}+S_{n-1}\\=C_k^0(n-1)^kk^{(n-1)+1}+C_k^1(n-1)^{k-1}k^{(n-1)+1}+\cdots+C_k^kk^{(n-1)+1}+S_{n-1}


将与n有关的项抽出来作为列向量,令 

X_{n-1}=\left\{\begin{matrix}(n-1)^kk^{(n-1)+1}\\(n-1)^{k-1}k^{(n-1)+1}\\\vdots\\(n-1)^0k^{(n-1)+1}\\S_{n-1}\end{matrix}\right\}


则 

X_{n}=\left\{\begin{matrix}n^kk^{n+1}\\n^{k-1}k^{n+1}\\\vdots\\n^0k^{n+1}\\S_{n}\end{matrix}\right\}

同样,有关SnSn的递推公式说明了系数矩阵AA的最后一行。而其他行仍然可以由二项式展开得到,只是相差了一个系数kk而已,这很容易解决。 
最后,有 

A=\left\{\begin{matrix}kC_k^0&&kC_k^1&&\cdots&&kC_k^k&&0\\0&&kC_{k-1}^0&&\cdots&&kC_{k-1}^{k-1}&&0\\\vdots&&\vdots&&\ddots&&\vdots&&\vdots\\0&&\cdots&&\cdots&&kC_0^0&&0\\C_k^0&&C_k^1&&\cdots&&C_k^k&&1\end{matrix}\right\}\tag{5}

 

部分题目

POJ3070利用了矩阵1,hdu3369利用了矩阵3和4,hdu3483利用了矩阵5。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值