http://acm.hdu.edu.cn/showproblem.php?pid=1575
題意 : 裸裸的矩陣相乘
思路 : 因為K比較大,所以我使用二進位最佳化,最後只要把主對角線上的數字加起來最後取下模即可。
//Danceonly#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef long long LL;const double INF = 100000007;const double eps = 1e-9;const int maxn = 15;const int mod = 9973;#define MIN(a,b) (a > b ? b : a)#define MAX(a,b) (a > b ? a : b)int maze[40][maxn][maxn];int ans[maxn][maxn],temp[maxn][maxn];bool tt[40];int N,K;void Fu(){ for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) ans[i][j] = temp[i][j];}void init(int a){ for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) { int sum = 0; for (int k=1;k<=N;k++) sum += (maze[a][i][k] * maze[a][k][j]) % mod; maze[a + 1][i][j] = sum % mod; }}void Add(int n){ for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) { int sum = 0; for (int k=1;k<=N;k++) sum += (ans[i][k] * maze[n][k][j]) % mod; temp[i][j] = sum % mod; } Fu();}void show(){ for (int k=1;k<=10;k++) { printf("k = %d\n",k); for (int i=1;i<=N;i++) { for (int j=1;j<=N;j++) printf("%d ",maze[k][i][j]); printf("\n"); } printf("\n"); }}int main(){ int T; scanf("%d",&T); while (T--) { scanf("%d%d",&N,&K); for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) { scanf("%d",&maze[1][i][j]); ans[i][j] = maze[1][i][j]; } for (int i=1;i<=32;i++) init(i); //show(); int e = 1,cnt = 0; while (K >= e) { e *= 2; cnt ++; } memset(tt,0,sizeof(tt)); for (int i=0;K;i++) { if (K >= e) { K -= e; tt[cnt - i] = 1; } else tt[cnt - i] = 0; e /= 2; } for (int i=1;i<=cnt;i++) if (tt[i]) Add(i+1); int sum = 0; for (int i=1;i<=N;i++) sum += ans[i][i]; printf("%d\n",sum % mod); } return 0;}