POJ 3233
思路:1.最基本的,需要用到矩阵快速幂 2.快速幂求完之后怎样快速求和?若逐项累加求和必然会超时,这时需要求递推公式:(1)若n为偶数,则:S(n) = A^(n/2)*S(n/2)+s(n/2);(2)若n为奇数 S(n) = A^(n/2+1) + S(n/2)*A^(n/2+1) + S(n/2),公式不难推,写几个就发现规律了。这样就把时间复杂度降下来了。
#include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int n, m; typedef struct Matrix{ int m[30][30]; Matrix(){ memset(m, 0, sizeof(m)); } }Matrix; Matrix mtAdd(Matrix A, Matrix B){ for(int i = 0;i < n;i ++) for(int j = 0;j < n;j ++){ A.m[i][j] += B.m[i][j]; A.m[i][j] %= m; } return A; } Matrix mtMul(Matrix A, Matrix B){ Matrix tmp; for(int i = 0;i < n;i ++) for(int j = 0;j < n;j ++) for(int k = 0;k < n;k ++){ tmp.m[i][j] += A.m[i][k]*B.m[k][j]; tmp.m[i][j] %= m; } return tmp; } Matrix mtPow(Matrix A, int k){ if(k == 1) return A; Matrix tmp = mtPow(A, k >> 1); Matrix res = mtMul(tmp, tmp); if(k&1) res = mtMul(res, A); return res; } Matrix mtSum(Matrix A, int k){ if(k == 1) return A; Matrix tmp = mtSum(A, k/2); if(k&1){ Matrix t = mtPow(A, k/2+1); Matrix tmp1 = mtMul(tmp, t); Matrix tmp2 = mtAdd(t, tmp); return mtAdd(tmp1, tmp2); }else return mtAdd(tmp, mtMul(mtPow(A, k/2), tmp)); } int main(){ int k, tmp; /* freopen("in.c", "r", stdin); */ while(~scanf("%d%d%d", &n, &k, &m)){ Matrix M; for(int i = 0;i < n;i ++) for(int j = 0;j < n;j ++){ scanf("%d", &tmp); M.m[i][j] = tmp; } M = mtSum(M, k); for(int i = 0;i < n;i ++){ for(int j = 0;j < n;j ++) printf("%d ", M.m[i][j]); puts(""); } } return 0; }