矩阵快速幂模板
矩阵快速幂是建立在快速幂基础上的。
其实就是快速幂的底数变成了矩阵
快速幂算法我就不多说了,下面是矩阵快速幂的解释。
这个是快速幂+快速幂取模的模板,结构体的重载乘号
struct mat { int m[maxn][maxn]; }unit; mat operator * (mat a, mat b) { mat ans; 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 += ((ll)a.m[i][k]*b.m[k][j])%mod; ans.m[i][j] = x%mod; } return ans; //返回的是一个矩阵 } void init_unit() { for(int i = 0; i < maxn; ++i) unit.m[i][i] = 1; //初始化单位矩阵 } mat poww(mat a, ll b) { mat ans = unit; mat base = a; while(b) { if(b&1) ans = ans*base; base = base*base; b >>= 1; } return ans; }
解释其实也没什么可以解释的。。就是快速幂从数变成了矩阵,初始化的时候用的是单位矩阵
下面给一个例题
hdu 1575
#include <iostream> #include <string.h> #include <cstdio> #define ll long long #define mod(x) ((x)%9973) using namespace std; int n; const int mod = 9973; const int maxn = 15; struct mat { int m[maxn][maxn]; }unit; mat operator * (mat a, mat b) { mat ans; 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 += ((ll)a.m[i][k]*b.m[k][j])%mod; ans.m[i][j] = x%mod; } return ans; //返回的是一个矩阵 } void init_unit() { for(int i = 0; i < maxn; ++i) unit.m[i][i] = 1; //初始化单位矩阵 } mat poww(mat a, ll b) { mat ans = unit; mat base = a; while(b) { if(b&1) ans = ans*base; base = base*base; b >>= 1; } return ans; } int main() { int T; scanf("%d", &T); init_unit(); while(T--) { ll k; mat a; scanf("%d%lld", &n, &k); for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) scanf("%d", &a.m[i][j]); a = poww(a, k); ll ans = 0; for(int i = 0; i < n; ++i) ans += a.m[i][i]; printf("%lld\n", ans%mod); } return 0; }
下面是矩阵快速幂打Fibonacci数列的例子,具体原理就不多说了,推一下就知道了
#include <iostream> #include <cstdio> #define ll long long using namespace std; const int MX = 4; const int mod = 10000; ll n; struct mat { ll m[MX][MX]; }unit; void unit_init() { for(int i = 0; i < MX; ++i) unit.m[i][i] = 1; } mat operator * (mat a, mat b) { mat ans; ll x; for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) { x = 0; for(int k = 0; k < 2; ++k) x += (a.m[i][k]*b.m[k][j])%mod; ans.m[i][j] = x%mod; } return ans; } mat poww(mat a, ll b) { mat ans = unit, base = a; while(b) { if(b&1) ans = ans*base; base = base*base; b >>= 1; } return ans; } int main() { unit_init(); while(scanf("%lld", &n) != EOF && n != -1) { mat a; a.m[0][0] = 1; a.m[0][1] = 1; a.m[1][0] = 1; a.m[1][1] = 0; // a = (1,1,1,0) mat ansmat = poww(a, n); ll ans = ansmat.m[0][1]; printf("%lld\n", ans); } return 0; }
化繁为简 大巧不工

浙公网安备 33010602011771号