题目链接:
https://vjudge.net/contest/71746#problem/E
题目大意:
现有一个n*k的矩阵A,以及一个k*n的矩阵B,在模6域下,求得矩阵C = A*B,并对
Cn∗n
的每一个元素求和,输出结果
分析:
直接暴力对C矩阵做快速幂,用类会爆空间,会数组写比较繁琐,且可能超时,所以可以得到以下式子
Cn∗n=(A∗B)n∗n=A∗(B∗A)∗(B∗A)⋯∗(B∗A)∗B
即可写作
Cn∗n=A∗(B∗A)n∗n−1∗B
而 B∗A 是一个6*6的矩阵,对它求快速幂便很容易了
代码:
(因为调了好多遍,写的很丑,调试输出也很多,只要#define ONLINE即可不调试输出
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
//#define ONLINE
using namespace std;
const int N = 1200;
struct mart
{
int n,m;
int a[12][12];
};
int n,m,x,y,q;
mart now;
int a[N][10],b[10][N],c[10][N],d[N][N];
typedef long long ll;
const int mod = 1000000007;
mart unit;
mart multiply(mart A,mart B)
{
mart C;
C.n = A.n;
C.m = B.m;
#ifndef ONLINE
cout<<"A.n = "<<A.n<<" B.m = "<<B.m<<endl;
#endif
for (int i = 1 ; i <= m ; i ++)
{
for (int j = 1 ; j <= m ; j ++ )
{
C.a[i][j] = 0;
for (int k = 1 ; k <= m ; k ++)
{
C.a[i][j] += A.a[i][k]*B.a[k][j];
C.a[i][j] %= 6;
}
}
}
return C;
}
mart quickpow(mart p,int t)
{
mart ans = unit;
while (t)
{
if (t&1)
ans = multiply(ans,p);
p = multiply(p,p);
t >>= 1;
}
#ifndef ONLINE
for (int i = 1 ; i <= m ; i ++)
{
for (int j = 1 ; j<= m ; j ++)
cout<< ans.a[i][j]<<'\t';
cout<<endl;
}
cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl;
#endif // ONLINE
return ans;
}
void init()
{
memset(now.a,0,sizeof(now.a));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(unit.a,0,sizeof(unit.a));
unit.m=m;
unit.n=m;
now.n = m;
now.m = m;
for (int i = 0 ; i < 12 ; i ++)
unit.a[i][i] = 1; //单位矩阵
return;
}
void read() //读入
{
for (int i = 1 ; i <= n ; i ++)
for (int j = 1; j <= m ; j ++)
scanf("%d",&a[i][j]);
for (int i = 1 ; i <= m ; i ++)
for (int j = 1; j <= n ; j ++)
scanf("%d",&b[i][j]);
return;
}
int main()
{
init();
while (~scanf("%d%d",&n,&m)&&(n||m)){
if (n==0&&m==0)
return 0;
init();
read();
for (int i = 1 ; i <= m ; i ++)
{
for (int j = 1 ; j <= m ; j ++)
{
now.a[i][j] = 0;
for (int k = 1 ; k <= n ; k ++)
{
now.a[i][j] += b[i][k] * a[k][j];
now.a[i][j] %= 6;
}
}
}
#ifndef ONLINE
cout<<"---------------------------------------------------"<<endl;
for (int i = 1 ; i <= m ; i ++)
{
for (int j = 1 ; j<= m ; j ++)
cout<< now.a[i][j]<<'\t';
cout<<endl;
}
cout<<"---------------------------------------------------"<<endl;
#endif // ONLINE
mart Ans = quickpow(now,n*n-1);
for (int i = 1 ; i <= m ; i ++)
{
for (int j = 1 ; j <= n ; j ++)
{
for (int k = 1 ; k <= m ; k ++)
{
c[i][j] += Ans.a[i][k]*b[k][j];
c[i][j] %= 6;
}
}
}
for (int i = 1 ; i <= n ; i ++)
{
for (int j = 1 ; j <= n ; j ++)
{
for (int k = 1 ; k <= m ; k ++)
{
d[i][j] += a[i][k] * c[k][j];
d[i][j] %= 6;
}
}
}
int ans = 0;
for (int i = 1 ; i <= n ; i ++)
{
for (int j = 1 ; j <= n ; j ++)
{
#ifndef ONLINE
cout<< d[i][j]<<'\t';
#endif // ONLINE
ans += d[i][j];
}
#ifndef ONLINE
cout<<endl;
#endif // ONLINE
}
printf("%d\n",ans);
}
}