思路:。。。雨神的骚题。。。(A*B)^t=A*B*A*B*A*......*B,根据结合律我们舍弃开头的A和结尾的B,那么(A*B)^t=A*B*(B*A)^t-1,之所以这样分解是因为A*B的范围有点大,,在结构体里开不了,而且容易超时,而(B*A)的只有10,10那么大,运算量小,并且易于写代码。。。。
下面附上代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define NUM 1005
#define mod 666
int n,x,m,t,T;
int A[NUM][10],B[10][NUM],N[NUM][10],D[NUM][NUM];
struct Matrix{
int a[10][10];
void init()
{
memset(a,0,sizeof(a));
for(int i=0;i<x;i++)
a[i][i]=1;
}
}C;
Matrix MUL(Matrix a,Matrix b)
{
Matrix ans;
for(int i=0;i<x;i++)
for(int j=0;j<x;j++)
{
ans.a[i][j]=0;
for(int k=0;k<x;k++)
ans.a[i][j]+=a.a[i][k]*b.a[k][j];
ans.a[i][j]%=mod;
}
return ans;
}
Matrix pow(Matrix c,int t)
{
Matrix ans;
ans.init();
while(t)
{
if(t&1)
ans=MUL(ans,c);
t/=2;
c=MUL(c,c);
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d %d",&n,&x,&m,&t);
for(int i=0;i<n;i++)
for(int j=0;j<x;j++)
scanf("%d",&A[i][j]);
for(int i=0;i<x;i++)
for(int j=0;j<m;j++)
scanf("%d",&B[i][j]);
for(int i=0;i<x;i++)
for(int j=0;j<x;j++)
{
C.a[i][j]=0;
for(int k=0;k<m;k++)
C.a[i][j]=(C.a[i][j]+B[i][k]*A[k][j])%mod;
}
Matrix ans;
t--;
ans=pow(C,t);
for(int i=0;i<n;i++)
for(int j=0;j<x;j++)
{
N[i][j]=0;
for(int k=0;k<x;k++)
N[i][j]=(N[i][j]+A[i][k]*ans.a[k][j])%mod;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
D[i][j]=0;
for(int k=0;k<x;k++)
D[i][j]=(D[i][j]+N[i][k]*B[k][j])%mod;
}
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
sum+=D[i][j];
sum%=mod;
}
printf("%d\n",sum);
}
return 0;
}