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;
}