题意:
n最大是1000,k最大是6,矩阵A规模n*k,矩阵B规模k*n,求矩阵(A*B)^(n*n)次方中每个数模6的和
思路:
求矩阵的幂可以用快速幂解决,但A*B最大是1000×1000的,快速幂的复杂度是1e9,会T
把(A*B)^(n*n)展开可以得到
(A*B)^(n*n)
=A*B * A*B * A*B *....
=A * B*A * B*A * B*A ... *B
=A*(B*A)^(n*n-1)*B
所以只要计算B*A,B*A是6×6的,所以会快
#include <bits/stdc++.h>
using namespace std;
#define mod 6
#define ll long long
int n,m;
ll a[1010][10],b[10][1010];
ll ans[1010][1010];
struct mat
{
ll num[10][10];
mat()
{
memset(num,0,sizeof num);
}
};
mat mul(mat a,mat b)
{
mat ans;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=m;k++)
{
ans.num[i][j]+=a.num[i][k]*b.num[k][j]%mod;
ans.num[i][j]%=mod;
}
}
}
return ans;
}
mat fpow(mat a,ll b)
{
mat tmp=a,ans;
for(int i=1;i<=m;i++)
ans.num[i][i]=1;
while(b)
{
if(b&1)
ans=mul(ans,tmp);
tmp=mul(tmp,tmp);
b/=2;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lld",&a[i][j]);
a[i][j]%=mod;
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%lld",&b[i][j]);
b[i][j]%=mod;
}
}
mat c;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=n;k++)
{
c.num[i][j]+=b[i][k]*a[k][j]%mod;
c.num[i][j]%=mod;
}
}
}
c=fpow(c,n*n-1);
memset(ans,0,sizeof ans);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=m;k++)
{
ans[i][j]+=a[i][k]*c.num[k][j]%mod;
ans[i][j]%=mod;
}
}
}
ll sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ll ss=0;
for(int k=1;k<=m;k++)
{
ss+=ans[i][k]*b[k][j]%mod;
ss%=mod;
}
sum+=ss;
}
}
printf("%lld\n",sum);
}
}