矩阵快速幂
Posted lihaozhe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵快速幂相关的知识,希望对你有一定的参考价值。
矩阵
定义
按照一个长方阵列排列的复数或实数集合。
看不懂?那就看图
设(A)是一个(n imes m)的矩阵,则(A)可以表示为
[
A_{n, m}=left[egin{array}{ll}A_{1,1}&A_{1,2}&cdots &A_{1,m}\A_{2,1}&A_{2,2}&cdots &A_{2,m}\vdots&vdots&ddots&vdots\A_{n,1}&A_{n,2}&cdots &A_{n,m}end{array}
ight]
]
这(m imes n)个数成为矩阵(A)的元素,简称为元。数(a_{i, j})位于矩阵(A)的第(i)行第(j)列,称为矩阵(A)的((i, j))元。
(m imes n)矩阵可记作矩阵(A)或矩阵(A_{m, n})
若矩阵(A)与矩阵(B)的行数和列数都相同,则称矩阵(A)与矩阵(B)是同型矩阵
实现:
const int N=100;
struct Matrix {
LL a[N][N]; int n, m;
Matrix(int type, int n, int m):n(n), m(m) {
memset(a, 0, sizeof(a));
}
void print() {
for (int i=0; i<n; i++, puts(""))
for (int j=0; j<m; j++)
printf("%d ", a[i][j]);
}
};
运算
加法
减法
数乘
咕咕咕~
乘法
当且仅当矩阵(A)的列数等于矩阵(B)的行数时,(A imes B)有定义
不放设(A)是一个(m imes n)的矩阵,(B)是一个(m imes p)的矩阵,那么(C=A imes B)是一个(n imes p)的矩阵,且(C_{i, j}=sum_{k=1}^mA_{i, k}B_{k, j})
理解:(C)矩阵的((i, j))元就是(A)矩阵中的第(i)行和(B)矩阵的第(j)列每项顺次相乘的和
更形象地理解,即为将(A)矩阵的第(i)行拿出来,顺时针旋转(90^circ)后平移使其与(B)矩阵的第(j)列对齐,将每对对齐的数分别相乘再求和即可。
在后面矩阵快速幂的应用中有例子模拟。
实现:
Matrix operator*(const Matrix &a, const Matrix &b) {
assert(a.m==b.n);
Matrix c(0, a.n, b.m);
for (int i=0; i<a.n; i++)
for (int j=0; j<b.m; j++)
for (int k=0; k<a.m; k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%P;
return c;
}
矩阵快速幂
问题
根据矩阵乘法的定义,一个(n imes n)的矩阵显然可以进行幂运算。
要求在(O(log n))时间内求出一个矩阵的(n)次幂
思路
对于整数,我们可以将指数二进制拆分后快速幂。
那么对于矩阵是否可以进行类似的操作呢?
显然可以。
实现矩阵乘法后,运算部分与快速幂无异。
注意快速幂要将答案的初值赋为(1),目的是使(ans imes x=x),避免在乘法时对(ans)讨论。那么是否也存在一个矩阵满足类似的性质呢?
确实存在。
对于任意一个(n imes n)的矩阵(x),存在(n imes n)的单位矩阵(I),满足(I imes x=x)。
很容易得到这个矩阵为
[
I=left[egin{array}{ll}1&0&0&cdots&0\0&1&0&cdots&0\0&0&1&cdots&0\vdots&vdots&vdots&ddots&vdots\0&0&0&cdots&1end{array}
ight]
]
实现
Matrix qpow(Matrix a, int b) {
assert(a.n==a.m);
Matrix ans(1, a.n, a.m);
for (; b; b>>=1, a=a*a) if (b&1) ans=ans*a;
return ans;
}
应用
快速转移线性递推式
以洛谷模板题洛谷P1939 【模板】矩阵加速(数列)为例
此题(f_n=f_{n-1}+f_{n-3})
用矩阵改写转移
[
left[egin{array}{ll}f_n\f_{n-1}\f_{n-2}\f_{n-3}end{array}
ight]=left[egin{array}{ll}1&0&1&0\1&0&0&0\0&1&0&0\0&0&1&0end{array}
ight] imesleft[egin{array}{ll}f_{n-1}\f_{n-2}\f_{n-3}\f_{n-4}end{array}
ight]
]
可以验证此矩阵转移式和题中线性递推式等价。
我们上面矩阵乘法讲的trick来验证一下答案矩阵的第一行,即(f_n)。
右边第一个矩阵的第一行顺时针旋转(90^circ)并平移使其与和第二个矩阵的第一列对齐
[
left[egin{array}{ll}1\0\1\0end{array}
ight]left[egin{array}{ll}f_{n-1}\f_{n-2}\f_{n-3}\f_{n-4}end{array}
ight]
]
将每对对齐的数相乘得
[
left[egin{array}{ll}1 imes f_{n-1}\0 imes f_{n-2}\1 imes f_{n-3}\0 imes f_{n-4}end{array}
ight]
]
求和,应用递推式得
[
f_{n-1}+f_{n-3}=f_n
]
答案矩阵后三行很容易验证。那么等式成立
将这个等式迭代下去得
[
left[egin{array}{ll}f_n\f_{n-1}\f_{n-2}\f_{n-3}end{array}
ight]=left[egin{array}{ll}1&0&1&0\1&0&0&0\0&1&0&0\0&0&1&0end{array}
ight]^{n-4} imesleft[egin{array}{ll}f_1\f_2\f_3\f_4end{array}
ight]
]
(f_1)到(f_4)均已知,那么利用矩阵快速幂即可在(O(log n))时间内求出(f)数列的第(n)项
以上是关于矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章