矩阵快速幂和普通的快速幂差不多,只不过写起来比较麻烦一点,需要重载*运算符。
模板:
struct mat { int m[maxn][maxn]; }unit; mat operator * (mat a,mat b) { mat ret; ll x; for(int i=0;i < n;i++) for(int j=0;j < n;j++) { x = 0; for(int k=0;k < n;k++) x += mod((ll)a.m[i][k]*b.m[k][j]); ret.m[i][j] = mod(x); } return ret; } void init_unit() //初始化单位矩阵 { for(int i=0;i < maxn;i++) unit.m[i][i] = 1; return; } mat pow_mat(mat a,ll n) { mat ret = unit; while(n) { if(n&1) ret = ret*a; a = a*a; n >>= 1; } return ret; }
例题:POJ3070
用矩阵快速幂求fib并取模10000
有这个定理就很好求了:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int moder = 10000; const int maxn = 110; #define mod(x) ((x)%moder) int n = 2; struct mat { int m[maxn][maxn]; }unit; mat operator * (mat a,mat b) { mat ret; ll x; for(int i=0;i < n;i++) for(int j=0;j < n;j++) { x = 0; for(int k=0;k < n;k++) x += mod((ll)a.m[i][k]*b.m[k][j]); ret.m[i][j] = mod(x); } return ret; } void init_unit() { for(int i=0;i < maxn;i++) unit.m[i][i] = 1; return; } mat pow_mat(mat a,ll n) { mat ret = unit; while(n) { if(n&1) ret = ret*a; a = a*a; n >>= 1; } return ret; } int main() { ll p; init_unit(); while(cin >> p) { if(p == -1) break; mat a; a.m[0][0] = 1; a.m[0][1] = 1; a.m[1][0] = 1; a.m[1][1] = 0; a = pow_mat(a,p); cout << a.m[0][1] << endl; } return 0; }
要注意的是maxn开小一点,不然本地会炸。