题意:
矩阵A是n*k,矩阵B是k*n,矩阵C = A*B,先求C^(n*n),再对矩阵C的每个元素对6取余,输出矩阵C的元素和
解题思路:
直接按照题目顺序来求会超时
( A*B )^( n*n ) = A*((B*A)^( n*n -1) )*B
先算P = (B*A)^( n*n -1)
再算A*P*B
这样转化的好处是在用矩阵快速幂计算时可以转化为6*6的,时间大大的减少
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int n,k;
int A[1050][10],B[10][1050],C[10][10],ret[10][10],I[10][10];
int pi[1050][1050],pj[1050][1050];
void mul(int a[10][10],int b[10][10])
{
memset(ret,0,sizeof(ret));
for(int i=0;i<k;i++)
for(int l=0;l<k;l++)
if(a[i][l])
for(int j=0;j<k;j++)
if(b[l][j])
ret[i][j] = (ret[i][j]+a[i][l]*b[l][j])%6;
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
a[i][j] = ret[i][j];
}
void mpower(int D[10][10],int x)
{
memset(I,0,sizeof(I));
for(int i=0;i<k;i++) I[i][i] = 1;
while(x)
{
if(x&1) mul(I,D);
x>>=1;
mul(D,D);
}
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
D[i][j] = I[i][j];
}
int main()
{
while(cin>>n>>k)
{
if(n==0 && k==0) break;
__int64 sum=0;
memset(C,0,sizeof(C));
for(int i=0;i<n;i++)
for(int j=0;j<k;j++)
cin>>A[i][j];
for(int i=0;i<k;i++)
for(int j=0;j<n;j++)
cin>>B[i][j];
for(int i=0;i<k;i++)
for(int l=0;l<n;l++)
if(B[i][l])
for(int j=0;j<k;j++)
if(A[l][j])
C[i][j] = (C[i][j]+B[i][l]*A[l][j])%6;
mpower(C,n*n-1);
memset(pi,0,sizeof(pi));
memset(pj,0,sizeof(pj));
for(int i=0;i<n;i++)
for(int l=0;l<k;l++)
if(A[i][l])
for(int j=0;j<k;j++)
if(C[l][j])
pi[i][j] = (pi[i][j]+A[i][l]*C[l][j])%6;
for(int i=0;i<n;i++)
for(int l=0;l<k;l++)
if(pi[i][l])
for(int j=0;j<n;j++)
if(B[l][j])
pj[i][j] = (pj[i][j]+pi[i][l]*B[l][j])%6;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
sum+=pj[i][j];
cout<<sum<<endl;
}
return 0;
}