POJ_3233
如果我们把S(k)写成递推式的话,就是S(k)=A*S(k-1)+A,这样就可以将S(k)表示成矩阵的形式,从而应用二分矩阵来快速求解S(k)了。
此外,在计算中间结果的时候尽量少取模,因为取模运算的效率确实很低。
#include<stdio.h> #include<string.h> #define MAXD 70 int N, K, M, cnt; struct Matrix { int a[MAXD][MAXD]; void init() { memset(a, 0, sizeof(a)); } }mat[510]; int multiply(int x, int y) { int i, j, k, z = ++ cnt; long long ans; for(i = 0; i < (N << 1); i ++) for(j = 0; j < (N << 1); j ++) { ans = 0; for(k = 0; k < (N << 1); k ++) ans += mat[x].a[i][k] * mat[y].a[k][j]; mat[z].a[i][j] = ans % M; } return z; } void init() { int i, j, k; cnt = 0; mat[0].init(); for(i = 0; i < N; i ++) for(j = 0; j < N; j ++) { scanf("%d", &k); mat[0].a[i][j] = mat[0].a[i][j + N] = k; if(i == j) mat[0].a[i + N][j + N] = 1; } } int powmod(int n) { int k; if(n == 1) return 0; k = powmod(n / 2); k = multiply(k, k); if(n & 1) k = multiply(k, 0); return k; } void solve() { int i, j, k; k = powmod(K); for(i = 0; i < N; i ++) { printf("%d", mat[k].a[i][N]); for(j = 1; j < N; j ++) printf(" %d", mat[k].a[i][j + N]); printf("\n"); } } int main() { while(scanf("%d%d%d", &N, &K, &M) == 3) { init(); solve(); } return 0; }