处理何种问题:用于优化加速一些线性关系式,可将一些时间复杂度降至O(logn)。
(如果题目上出现 1e18 之类的数据范围,就可以往矩阵快速幂上想了)
性能:具体的时间复杂度为O(edge * edge * log n),edge为矩阵的阶数。
原理:矩阵乘法性质、快速幂。
实现步骤:以斐波那契数列为例
公式为: F[i] = F[i-1] + F[i-2],根据公式将此转化为矩阵公式
备注:需要进行 *、= 符号的重载,套用快速幂模板,但取模在 * 重载函数中。
输入样例解释:
99999999999999 //f(n)
输出样例解释:
626 //结果
--------------------------------------------------------------------
代码:
///此代码为求斐波那契数列矩阵快速幂,若要求其他矩阵快速幂注意更改标记 <--- 的行。 #include<iostream> #include<cstdio> #include<string.h> #include<algorithm> using namespace std; const long long mod=10000;/// <--- const int edge=2;/// <--- struct Matrix ///定义矩阵,重载*,=; { long long a[edge][edge]; Matrix() { memset(a,0,sizeof(a));///构造函数,初始化矩阵 } Matrix operator *(const Matrix b) ///自定义矩阵乘法 { Matrix temp; for(int i=0; i<edge; ++i) for(int j=0; j<edge; ++j) for(int k=0; k<edge; ++k) { temp.a[i][j]+=a[i][k]*b.a[k][j]; temp.a[i][j]%=mod;///在此取模 } return temp; } }; Matrix m_fpow(Matrix a,long long n) { Matrix Ans; Ans.a[0][0]=Ans.a[1][1]=1;///初始化为单位矩阵 // <--- while(n!=0)///套用快速幂 { if(n&1) Ans=Ans*a; n=n>>1; a=a*a; } return Ans; } int main() { Matrix Ans,a,b; long long n; scanf("%lld",&n); if(n==0) printf("0 "); else if(n==1) printf("1 "); else { a.a[0][0]=a.a[0][1]=a.a[1][0]=1;///初始化,不同的dp关系对应不同的矩阵 // <--- b.a[0][0]=b.a[1][0]=1; /// <--- Ans=m_fpow(a,n-2)*b; printf("%lld ",Ans.a[0][0]); } return 0; }