先来回顾一下整数快速幂的代码:
public static long qmi(long b, int i,int mod) {
long ans=1;
for(;i>0;i>>=1,b=b*b%mod)if((i&1)==1)ans = ans * b % mod;
return ans;
}
(注意如果要对底数取模,注意底数是否可能是负数。如果可能是的话,取模函数写作如下形式:
static int ff(int x,int m) {
return (x%m+m)%m;
}
整数快速幂,是用来计算AB %C的,时间复杂度在O(logB)以内(每次的位运算相当于把余下的B折半)。当然,还可以用快速乘来进一步优化。
矩阵快速幂,就是将整数A变为常数矩阵A。有什么用呢?
第一步,列出第n项递推式f(n)=f(n-1)+f(n-2)
第二步,建立矩阵递推式,找到转移矩阵
简写成T*A(n-1)=A(n),
T矩阵就是转移矩阵,而且一定是一个常数矩阵,
由此得到A(n)=Tn-1 *A(1)
计算Tn-1 的工作就可以交给矩阵快速幂了,A(1)手动计算,就可以得到A(n)了。
基础知识:
(1)矩阵乘法
其中c[i][j]为A的第i行与B的第i列的乘积的和,即
矩阵乘法时间复杂度O(n3)
矩阵乘法前提是A的行数等于B的列数(可见矩阵乘法不满足交换律),但是如果是方阵则不存在这个问题。
矩阵快速幂的代码,就是把乘法改成矩阵乘法,呈上:
一些简单的递推式
1.f(n)=af(n-1)+bf(n-2)+c;(a,b,c是常数)
2.f(n)=c^n-f(n-1) ;(c是常数)
矩阵快速幂板子:
public class Main {
static int maxn=10,mod=1000000007;
static class Matrix{
long m[][]=new long[maxn][maxn];
}
static Matrix multi(Matrix a,Matrix b,int N) {//N为T方阵阶数,下同
Matrix ans=new Matrix();
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++) {
ans.m[i][j]+=a.m[i][k]*b.m[k][j]%mod;
ans.m[i][j]%=mod;
}
return ans;
}
static Matrix qmi_m(Matrix a,int n,int N) {
Matrix ans=new Matrix();
for(int i=0;i<N;i++) {
ans.m[i][i]=1;
}
while(n>0) {
if((n&1)>0) {
ans=multi(ans,a,N);
}
a=multi(a,a,N);
n>>=1;
}
return ans;
}
static long qmi(long b, int i,int mod) {
long ans=1;
for(;i>0;i>>=1,b=b*b%mod)if((i&1)==1)ans = ans * b % mod;
return ans;
}
public static void main(String args[]) {
Matrix T=new Matrix();
//不要忘记初始化T
Matrix res=qmi_m(T,n-1,N);
}
}