题面:
4 2 5 5 4 4 5 4 0 0 4 2 5 5 1 3 1 5 6 3 1 2 3 0 3 0 2 3 4 4 3 2 2 5 5 0 5 0 3 4 5 1 1 0 5 3 2 3 3 2 3 1 5 4 5 2 0 0
14 56
解题:
题意:是将n*k和k*n的矩阵的乘积,求n*n次方后求和。
虽然用了矩阵快速幂,但是依旧会超时,因为n会达到1000计算量仍旧太大,看了一种解法是分解为A*(B*A)^(n*n-1)*B。着实很难想到,但是接触过之后,以后就可以运用了,也算是一种技巧吧。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,k;
struct matrix
{
int map[7][7];
};
matrix mult(matrix a,matrix b)
{
matrix c;
memset(c.map,0,sizeof(c.map));
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
for(int m=1;m<=k;m++)
{
c.map[i][j]=(c.map[i][j]+a.map[i][m]*b.map[m][j]);
}
c.map[i][j]%=6;
}
}
return c;
}
matrix pow_mult(matrix a,int x)
{
matrix c;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
c.map[i][j]=(i==j);
}
}
for(;x;x>>=1)
{
if(x&1)c=mult(c,a);
a=mult(a,a);
}
return c;
}
int a[1005][7],b[7][1005],final[7][1005],mid[7][7],last[1005][1005],sum;
int main()
{
while(scanf("%d%d",&n,&k))
{
if(n==0&&k==0)break;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
scanf("%d",&a[i][j]);
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
scanf("%d",&b[i][j]);
}
memset(mid,0,sizeof(mid));
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
for(int m=1;m<=n;m++)
{
mid[i][j]=mid[i][j]+b[i][m]*a[m][j];
}
mid[i][j]%=6;
}
}
matrix ans;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
ans.map[i][j]=mid[i][j];
}
}
ans=pow_mult(ans,n*n-1);
memset(final,0,sizeof(final));
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
for(int m=1;m<=k;m++)
{
final[i][j]=final[i][j]+ans.map[i][m]*b[m][j];
}
final[i][j]%=6;
}
}
memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int m=1;m<=k;m++)
{
last[i][j]=(last[i][j]+a[i][m]*final[m][j]);
}
last[i][j]%=6;
}
}
sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
sum+=last[i][j];
}
}
cout<<sum<<endl;
}
return 0;
}HDU 4965 Fast Matrix Calculation
原文:http://blog.csdn.net/david_jett/article/details/46432929