HDU 1575 Tr A
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; }