写在前面:
定义矩阵:
struct Matrix{
LL a[MAX_K][MAX_K],n,m;//n行 m列
Matrix(int _n = 0,int _m = 0):n(_n),m(_m){rep(i,1,n)rep(j,1,m) a[i][j]=0;}
void dw(int _n,int _m){n=_n,m=_m;rep(i,1,n)rep(j,1,m) a[i][j]=(i==j?1:0);}
LL& operator ()(int i,int j){return a[i][j];}
void print(){rep(i,1,n) rep(j,1,m) printf("%I64d%c",a[i][j],j==m?'\n':' ');}
};
矩阵乘法:
优化递推主要应用到矩阵乘法(当然如果要说特征根方程求通项的话....),先简单介绍一下矩阵乘法(可以无视掉):
定义矩阵A,B。
当且仅当A .m==B.n时 矩阵A,B可乘。
A(x,y)*B(y,z)=C(x,z)
其中每一个元素 Cij=Aik*Bkj (1<=k<=y)
矩阵乘法满足结合律与分配律,结合律是矩阵能够优化递推的关键所在。
矩阵优化递推的一般方法:
构建一个N维向量A(1,n),一个N*N的转移矩阵B(n,n)
A(1,n)*B(n,n)=C(1,n) 我们发现C与A 同阶,C 又能乘B ...就这样一直递推到需要的一项。
但一般先写出A和下一项C ,再来倒推转移矩阵B
矩阵快速幂:
矩阵乘法一次是O(n^3)的,单凭矩阵乘法优化递推是不可行的。
当然,上面说过矩阵乘法满足结合律,我们考虑矩阵快速幂!
比如要得到递推式的第K项,相当于计算 A*B^K=C
B^K可以通过矩阵快速幂O(N^3logK)算出
Matrix operator *(Matrix a,Matrix b){//矩阵乘法
Matrix res(a.n,b.m);
rep(i,1,a.n) rep(j,1,b.m) rep(k,1,a.m)
(res(i,j)+=a(i,k)*b(k,j))%=MOD;
return res;
}
Matrix operator ^(Matrix a,LL x){//快速幂
Matrix res;res.dw(a.n,a.m);
for (;x;a=a*a,x>>=1)
if (x&1) res=res*a;
return res;
}
矩阵的重要性质:
贴吧大神说矩阵也满足费马小定理?(亟待验证)