矩阵快速幂——分治
时间复杂度 O(log n)
高效率计算矩阵的高次方
原理:矩阵乘法的结合律
比如:A*A*A*A*A*A ==> (A*A)*(A*A)*(A*A)
要做到减少重复计算,即充分利用现有的计算结果,考虑使用二分
求A^19次时,使用二进制把问题离散化,转为求(A16)*(A2)*(A)
矩阵快速幂模板 求Ak
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstring> const int mod=1e9+7; typedef long long ll; using namespace std; struct Mat { ll m[101][101]; }a,e; //a是输入的矩阵,e是单位矩阵 ll n,k; Mat Mul(Mat x,Mat y) { //矩阵乘 返回乘后的矩阵 Mat ans; memset(ans.m,0,sizeof(ans.m)); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) for(int k=1; k<=n; k++) ans.m[i][j]=ans.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod; return ans; } Mat ksm(Mat x,ll b) { Mat ans=e; while(b) { if(b&1) ans=Mul(ans,x); x=Mul(x,x); b>>=1; } return ans; } int main( ) { cin>>n>>k; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a.m[i][j]; for(int i=1;i<=n;i++) e.m[i][i]=1; Mat ans=ksm(a,k); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) cout<<ans.m[i][j]%mod<<" "; cout<<endl; } return 0; }
例题:https://www.luogu.org/problem/P3390
矩阵快速幂求斐波那契
在斐波那契数列中
f[i] = 1*f[i-1] + 1*f[i-2]
f[i-1] = 1*f[i-1] + 0*f[i-2];
用矩阵表示:
或者
对于斐波那契额,构造结构体
代码
#include <iostream> #include <cstring> using namespace std; struct Mat { long long A[2][2]; }; Mat Mul(Mat x, Mat y) { Mat ans; memset(ans.A, 0, sizeof(ans.A)); for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { for(int k = 0; k < 2; k++) { ans.A[i][j] = ans.A[i][j] + x.A[i][k] * y.A[k][j]; } } } return ans; } void quickpow(int n) { Mat x,res; //x为输入矩阵 x.A[0][0] = x.A[0][1] = x.A[1][0] = 1; x.A[1][1] = 0; memset(res.A, 0, sizeof(res.A)); //单位矩阵 for(int i = 0; i < 2; i++) res.A[i][i] = 1; while(n) { if(n & 1) res = Mul(res, x); x = Mul(x, x); n >>= 1; } cout << res.A[0][1] << endl; } int main( ) { int n; while(cin >> n) { quickpow(n); } return 0; }
例题:http://poj.org/problem?id=3070