http://acm.hdu.edu.cn/showproblem.php?pid=4965
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能取1000时,果断CE(栈内存爆了)+TLE,然后就不知所措
最后队友将C^(n*n)写成(A*B)*(A*B)……才反应过来,利用矩阵点结合律,计算(B*A)^(n*n-1)就行了,思维太死了。。。
#include <cstdio> #include <cstring> using namespace std; int n,k,ans; const int MAXN=1001; const int MOD=6; struct Matrix { int x[MAXN][MAXN]; void clear() { memset(x,0,sizeof(x)); }; }a,b,c,tmp,pro; void mul(const Matrix& x,const Matrix& y,int bound_1,int bound_2,int bound_3) {//刚开始写了个带优化O(n^3)的乘法,为了减少更改其他代码,故参数多加了3个循环变量点上界以使其适用于所有情况 tmp.clear(); for(int i=0;i<bound_1;++i) for(int j=0;j<bound_2;++j) for(int k=0;k<bound_3;++k) tmp.x[i][j]=(tmp.x[i][j]+x.x[i][k]*y.x[k][j])%MOD; } void quick_pow(Matrix& x,int num) {//矩阵快速幂 pro.clear(); for(int i=0;i<k;++i) pro.x[i][i]=1; while(num>0) { if((num&1)==1) { mul(pro,x,k,k,k); pro=tmp; } mul(x,x,k,k,k); x=tmp; num>>=1; } } int main() { while(scanf("%d%d",&n,&k),n!=0&&k!=0) { a.clear(); b.clear(); c.clear(); for(int i=0;i<n;++i) { for(int j=0;j<k;++j) scanf("%d",&a.x[i][j]); } for(int i=0;i<k;++i) { for(int j=0;j<n;++j) { scanf("%d",&b.x[i][j]); } } mul(b,a,k,k,n);//由于矩阵太大,函数返回矩阵的话oj直接判CE,只能用全局变量 c=tmp; quick_pow(c,n*n-1); c=pro; mul(a,c,n,n,k); c=tmp; mul(c,b,n,n,k); c=tmp; ans=0; for(int i=0;i<n;++i) for(int j=0;j<n;++j) ans+=c.x[i][j]; printf("%d\n",ans); } return 0; }
#include <cstdio> #include <cstring> using namespace std; const int MAXN=6; const int MOD=6; int n,m,ans; int a[1001][1001],b[1001][1001],c[1001][1001]; struct Matrix { int x[MAXN][MAXN]; Matrix() { memset(x,0,sizeof(x)); } void clear() { memset(x,0,sizeof(x)); }; }cur; Matrix mul(const Matrix& x,const Matrix& y) { Matrix res; for(int i=0;i<MAXN;++i) for(int j=0;j<MAXN;++j) for(int k=0;k<MAXN;++k) res.x[i][j]=(res.x[i][j]+x.x[i][k]*y.x[k][j])%MOD; return res; } Matrix quick_pow(Matrix& x,int num) {//矩阵快速幂 Matrix res; for(int i=0;i<MAXN;++i) res.x[i][i]=1; while(num>0) { if((num&1)==1) res=mul(res,x); x=mul(x,x); num>>=1; } return res; } int main() { while(scanf("%d%d",&n,&m),n!=0&&m!=0) { for(int i=0;i<n;++i) for(int j=0;j<m;++j) scanf("%d",&a[i][j]); for(int i=0;i<m;++i) for(int j=0;j<n;++j) scanf("%d",&b[i][j]); cur.clear(); for(int i=0;i<m;++i) for(int j=0;j<m;++j) for(int k=0;k<n;++k) cur.x[i][j]=(cur.x[i][j]+b[i][k]*a[k][j])%MOD; cur=quick_pow(cur,n*n-1); memset(c,0,sizeof(c)); for(int i=0;i<n;++i) for(int j=0;j<n;++j) for(int k=0;k<m;++k) c[i][j]=(c[i][j]+a[i][k]*cur.x[k][j])%MOD; memset(a,0,sizeof(a)); for(int i=0;i<n;++i) for(int j=0;j<n;++j) for(int k=0;k<m;++k) a[i][j]=(a[i][j]+c[i][k]*b[k][j])%MOD; ans=0; for(int i=0;i<n;++i) for(int j=0;j<n;++j) ans+=a[i][j]; printf("%d\n",ans); } return 0; }