Shu-How Zの小窝

Loading...

矩阵快速幂详解

矩阵快速幂详解

这篇博客会讲解:
什么是矩阵快速幂?有什么用?怎么实现的?
矩阵快速幂的原理是什么?如何快速构造矩阵?
注:矩阵快速幂不需要具体学习线性代数。这篇博客能保证没学过线性代数的人也能听懂


前置知识:矩阵及矩阵乘法

一个矩阵类似于一个二维数组,例如一个 \(n\)\(m\) 列的矩阵 \(A\) 长成这样

\[A= \begin{pmatrix} A_{1,1}&A_{1,2}&...&A_{1,m}\\ A_{2,1}&A_{2,2}&...&A_{2,m}\\ ......\\ A_{n,1}&A_{n,2}&...&A_{n,m} \end{pmatrix} \]

其中 \(A_{i,j}\) 表示矩阵 \(A\)\(i\) 行第 \(j\) 列的元素,翻译成C++语言就是 \(A[i][j]\)
矩阵乘法就是将两个矩阵相乘。相乘的两个矩阵中,第一个矩阵的列数必须等于第二个矩阵的行数才能相乘。对于一个 \(n\)\(m\) 列的矩阵 \(A\) 和一个 \(m\)\(k\) 列的矩阵 \(B\) ,做乘法时具体规则如下:

\[AB= \begin{pmatrix} \sum_{i=1}^{m}A_{1,i}B_{i,1}&\sum_{i=1}^{m}A_{1,i}B_{i,2}&...&\sum_{i=1}^{m}A_{1,i}B_{i,k}\\ \sum_{i=1}^{m}A_{2,i}B_{i,1}&\sum_{i=1}^{m}A_{2,i}B_{i,2}&...&\sum_{i=1}^{m}A_{2,i}B_{i,k}\\ ......\\ \sum_{i=1}^{m}A_{n,i}B_{i,1}&\sum_{i=1}^{m}A_{n,i}B_{i,2}&...&\sum_{i=1}^{m}A_{n,i}B_{i,k} \end{pmatrix} \]

矩阵乘法满足结合律但不满足结合律,读者自证不难。


1.矩阵快速幂的引入

矩阵快速幂是快速计算线性递推的方法。
递推不难理解。线性就是递推式里全是一次项,没有二及以上次项
举个例子:求第 \(n\) 项斐波那契额数列。
\(n>1e8\) 时,很明显直接递推会超时
这时就需要矩阵快速幂了
注意到斐波那契额数只和前两项有关系,那我们可以建立这样一个矩阵

\[\begin{pmatrix} x\\ y \end{pmatrix} \]

若当前矩阵递推到了第 \(i\) 项,则 \(x\) 表示第 \(i-2\) 项,\(y\) 表示第 \(i-1\)项。
那每次转移就可以看成一个 \(2\times 2\) 的矩阵乘上它。
设这个矩阵是

\[\begin{pmatrix} a&b\\ c&d \end{pmatrix} \]

那么根据斐波那契额数列的前几项就可以列出几个方程,解方程,就可以得到这个矩阵:

\[\begin{pmatrix} 0&1\\ 1&1 \end{pmatrix} \]

也就是说,第 \(n\) 项斐波那契额数就是这个矩阵乘 \(\begin{pmatrix}1\\1\end{pmatrix}\),重复乘 \(n\) 次。因为斐波那契额数列的前两项是两个1,所以乘上\(\begin{pmatrix}1\\1\end{pmatrix}\)
那么只需要算出:

\[\begin{pmatrix} 0&1\\ 1&1 \end{pmatrix}^n \begin{pmatrix} 1\\1 \end{pmatrix} \]

就可以算出第 \(n\) 项了
很明显\(\begin{pmatrix} 0&1\\ 1&1 \end{pmatrix}^n\)的部分可以用快速幂加速,最后再乘上\(\begin{pmatrix} 1\\1 \end{pmatrix}\),就可以快速算出第 \(n\) 项了。时间复杂度 \(O(\log n)\),因为快速幂的复杂度是 \(O(\log n)\)


2.矩阵快速幂的原理及如何快速构造矩阵

很明显如果纯靠解方程求矩阵很慢,递推式稍微长点可能就得列一堆方程。赛场上又没时间,很可能没解完就交卷了。
那有没有快速构造矩阵的方法呢?

(在这里就不说推导过程了因为作者也是解了几个矩阵才发现的规律所以直接说结论)
如果递推式长成这样:

\[f_i=a_1f_{i-1}+a_2f_{i-2}+...+a_kf_{i-k} \]

那么矩阵长成这样:

\[\begin{pmatrix} 0&1&0&...&0\\ 0&0&1&...&0\\ ...\\ 0&0&0&...&1\\ a_k&a_{k-1}&a_{k-2}&...&a_1 \end{pmatrix} \]

其中最左边那一列,除了最后一行,其他的都是零。
右上角那部分的对角线上都是 \(1\) ,其他位置是 \(0\) (其实就是单位矩阵)。
最下面那行就是按照我写的排列
做一次乘法,得到:

\[\begin{pmatrix} 0&1&0&...&0\\ 0&0&1&...&0\\ ...\\ 0&0&0&...&1\\ a_k&a_{k-1}&a_{k-2}&...&a_1 \end{pmatrix} \begin{pmatrix} f_{i-k}\\ f_{i-k+1}\\ f_{i-k+2}\\ ...\\ f_{i-1} \end{pmatrix} = \begin{pmatrix} 1\times f_{i-k+1}\\ 1\times f_{i-k+2}\\ 1\times f_{i-k+3}\\ ...\\ a_kf_{i-k}+a_{k-1}f_{i-k+1}+a_{k-2}f_{i-k+2}+...+a_1f_{i-1} \end{pmatrix} = \begin{pmatrix} f_{i-k+1}\\ f_{i-k+2}\\ f_{i-k+3}\\ ...\\ f_i \end{pmatrix} \]

而矩阵 \(\begin{pmatrix} f_{i-k+1}\\ f_{i-k+2}\\ f_{i-k+3}\\ ...\\ f_i \end{pmatrix}\) 就是我们经过第 \(i\) 次转移后的矩阵。所以根据矩阵的乘法结合律,我们可以把这些矩阵先累成起来,再乘我们的初始矩阵,这也是矩阵快速幂的原理。


如有问题欢迎评论

posted @ 2025-02-27 21:03  wangyanxiao  阅读(852)  评论(0)    收藏  举报