算法 | 矩阵加速算法
矩阵加速算法:使用矩阵加速数列递推式的计算。
构造矩阵形式递推式
例如递推式:
$$ a_n=a_{n-1}+a_{n-3},\ 其中\ a_1=a_2=a_3=1 $$
如果直接用这个多项式形式递推式来进行递推,时间复杂度为:$O(n)$,接下来的操作就是为了加速这个过程。
我们列出递推式对应的方程组:
$$ \begin{cases} a_n&=&a_{n-1}&&+a_{n-3}\\ a_{n-1}&=&a_{n-1}&\\ a_{n-2}&=&&+a_{n-2} \end{cases} $$
写成矩阵形式:
$$ \begin{bmatrix} a_{n}\\ a_{n-1}\\ a_{n-2} \end{bmatrix} = \begin{bmatrix} 1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} a_{n-1}\\ a_{n-2}\\ a_{n-3} \end{bmatrix} $$
那么即可得到每一项:
$$ \begin{bmatrix} a_{n}\\ a_{n-1}\\ a_{n-2} \end{bmatrix} = \begin{bmatrix} 1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix}^{n-3} \begin{bmatrix} 1\\ 1\\ 1 \end{bmatrix} $$
矩阵快速幂
由于矩阵乘法也满足 $M^{2n}=(M^2)^n$,因此类比数乘快速幂,矩阵也可以用快速幂算法,只需将数乘换成矩阵乘法即可。
对于上述例子:
$$ \begin{bmatrix} a_{n+3}\\ a_{n+2}\\ a_{n+1} \end{bmatrix} = M^{n} \begin{bmatrix} 1\\ 1\\ 1 \end{bmatrix} ,\ 其中\ M=\begin{bmatrix} 1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix} $$
通过快速幂来处理 $M^n$,时间复杂度为 $O(\log n)$,实现了递推计算的加速。
模板
$n$ 阶方阵乘法:
vector<vector<ll>> mat_mul(vector<vector<ll>> a, vector<vector<ll>> b, ll mod)
{
int n = a.size();
vector<vector<ll>> res(n, vector<ll>(n));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
res[i][j] = (res[i][j] + a[i][k] * b[k][j] % mod) % mod;
return res;
}
矩阵快速幂:
vector<vector<ll>> mat_pow(vector<vector<ll>> a, ll b, ll mod)
{
int n = a.size();
vector<vector<ll>> res(n, vector<ll>(n));
for (int i = 0; i < n; i++)
res[i][i] = 1;
while (b)
{
if (b % 2)
res = mat_mul(res, a, mod);
a = mat_mul(a, a, mod);
b /= 2;
}
return res;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi