poj3233(矩阵快速幂)
poj3233 http://poj.org/problem?id=3233
给定n ,k,m
然后是n*n行,
我们先可以把式子转化为递推的,然后就可以用矩阵来加速计算了。 矩阵是加速递推计算的一个好工具
我们可以看到,矩阵的每个元素都是一个矩阵,其实这计算一个分块矩阵,我们可以把分块矩阵展开,它的乘法和普通矩阵的乘法是一样的。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1 << 30; 17 int MOD; 18 /* 19 矩阵的元素是矩阵,即分块矩阵 20 分块矩阵的乘法和普通矩阵的乘法是一样的 21 */ 22 struct Matrix 23 { 24 int mat[66][66]; 25 int size; 26 Matrix(int n) 27 { 28 size = n; 29 } 30 void makeZero() 31 { 32 for (int i = 0; i < size; ++i) 33 { 34 for (int j = 0; j < size; ++j) 35 mat[i][j] = 0; 36 } 37 } 38 void makeUnit() 39 { 40 for (int i = 0; i < size; ++i) 41 { 42 for (int j = 0; j < size; ++j) 43 mat[i][j] = (i == j); 44 } 45 } 46 }; 47 48 Matrix operator*(const Matrix &lhs, const Matrix &rhs) 49 { 50 Matrix ret(lhs.size); 51 ret.makeZero(); 52 for (int i = 0; i < lhs.size; ++i) 53 { 54 for (int j = 0; j < lhs.size; ++j) 55 { 56 for (int k = 0; k < lhs.size; ++k) 57 { 58 ret.mat[i][j] += (lhs.mat[i][k] * rhs.mat[k][j]); 59 if (ret.mat[i][j] >= MOD) 60 ret.mat[i][j] %= MOD; 61 } 62 } 63 } 64 return ret; 65 } 66 Matrix operator^(Matrix &a, int k) 67 { 68 Matrix ret(a.size);//单位矩阵 69 ret.makeUnit(); 70 while (k) 71 { 72 if (k & 1) 73 { 74 ret = ret * a; 75 } 76 a = a * a; 77 k >>= 1; 78 } 79 return ret; 80 } 81 int main() 82 { 83 int n, k, m, i, j; 84 while (scanf("%d%d%d", &n, &k, &MOD) != EOF) 85 { 86 Matrix a(2*n); 87 Matrix tmp(2*n);; 88 a.makeZero(); 89 for (i = 0; i < n; ++i) 90 { 91 for (j = 0; j < n; ++j) 92 { 93 scanf("%d", &a.mat[i][j]); 94 if (a.mat[i][j] >= MOD) 95 a.mat[i][j] %= MOD; 96 tmp.mat[i][j] = a.mat[i][j]; 97 tmp.mat[i][n + j] = a.mat[i][j]; 98 } 99 a.mat[n + i][i] = a.mat[n + i][n + i] = 1; 100 } 101 a = a ^ (k - 1); 102 Matrix ans(2*n); 103 ans.makeZero(); 104 m = 2 * n; 105 for (i = 0; i < n; ++i) 106 { 107 for (j = 0; j < n; ++j) 108 { 109 for (k = 0; k < m; ++k) 110 { 111 ans.mat[i][j] += tmp.mat[i][k] * a.mat[k][j]; 112 if (ans.mat[i][j] >= MOD) 113 ans.mat[i][j] %= MOD; 114 } 115 } 116 } 117 for (i = 0; i < n; ++i) 118 { 119 for (j = 0; j < n; ++j) 120 { 121 j == n - 1 ? printf("%d\n", ans.mat[i][j]) : printf("%d ", ans.mat[i][j]); 122 } 123 } 124 } 125 return 0; 126 }
当然了,我们还可以用二分的方法方法来计算
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1 << 30; 17 int MOD; 18 /* 19 矩阵的元素是矩阵,即分块矩阵 20 分块矩阵的乘法和普通矩阵的乘法是一样的 21 */ 22 struct Matrix 23 { 24 int mat[66][66]; 25 int size; 26 Matrix(int n) 27 { 28 size = n; 29 } 30 void makeZero() 31 { 32 for (int i = 0; i < size; ++i) 33 { 34 for (int j = 0; j < size; ++j) 35 mat[i][j] = 0; 36 } 37 } 38 void makeUnit() 39 { 40 for (int i = 0; i < size; ++i) 41 { 42 for (int j = 0; j < size; ++j) 43 mat[i][j] = (i == j); 44 } 45 } 46 }; 47 48 Matrix operator*(const Matrix &lhs, const Matrix &rhs) 49 { 50 Matrix ret(lhs.size); 51 ret.makeZero(); 52 for (int i = 0; i < lhs.size; ++i) 53 { 54 for (int j = 0; j < lhs.size; ++j) 55 { 56 for (int k = 0; k < lhs.size; ++k) 57 { 58 ret.mat[i][j] += (lhs.mat[i][k] * rhs.mat[k][j]); 59 if (ret.mat[i][j] >= MOD) 60 ret.mat[i][j] %= MOD; 61 } 62 } 63 } 64 return ret; 65 } 66 Matrix operator^(Matrix &a, int k) 67 { 68 Matrix ret(a.size);//单位矩阵 69 ret.makeUnit(); 70 while (k) 71 { 72 if (k & 1) 73 { 74 ret = ret * a; 75 } 76 a = a * a; 77 k >>= 1; 78 } 79 return ret; 80 } 81 Matrix operator+(const Matrix &lhs, const Matrix &rhs) 82 { 83 Matrix ret(lhs.size); 84 ret.makeZero(); 85 for (int i = 0; i < lhs.size; ++i) 86 { 87 for (int j = 0; j < lhs.size; ++j) 88 { 89 ret.mat[i][j] = lhs.mat[i][j] + rhs.mat[i][j]; 90 if (ret.mat[i][j] >= MOD) 91 ret.mat[i][j] %= MOD; 92 } 93 } 94 return ret; 95 } 96 Matrix matrixSum(Matrix a, int k) 97 { 98 if (k == 1) 99 return a; 100 Matrix ret = matrixSum(a, k / 2); 101 if (k & 1) 102 { 103 Matrix tmp = a ^ (k / 2 + 1); 104 ret = ret * tmp + ret + tmp; 105 } 106 else 107 { 108 Matrix tmp = a ^ (k / 2); 109 ret = ret*tmp + ret; 110 } 111 return ret; 112 } 113 int main() 114 { 115 int n, k, m, i, j; 116 while (scanf("%d%d%d", &n, &k, &MOD) != EOF) 117 { 118 Matrix a(n); 119 for (i = 0; i < n; ++i) 120 { 121 for (j = 0; j < n; ++j) 122 { 123 scanf("%d", &a.mat[i][j]); 124 if (a.mat[i][j] >= MOD) 125 a.mat[i][j] %= MOD; 126 } 127 } 128 Matrix ans = matrixSum(a, k); 129 for (i = 0; i < n; ++i) 130 { 131 for (j = 0; j < n; ++j) 132 j == n - 1 ? printf("%d\n", ans.mat[i][j]) : printf("%d ", ans.mat[i][j]); 133 } 134 return 0; 135 } 136 }