标签:hdu multi_university 矩阵快速幂 思维
题面:
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
标签:hdu multi_university 矩阵快速幂 思维
原文地址:http://blog.csdn.net/david_jett/article/details/46432929