POJ 3233 矩阵连乘+二分
这题2829MS险过。。应该会有更好的方法 首先矩阵连乘这没说的 重要的是在于二分 有公式 k为奇数时 s(k)=a+(a+a^(k/2+1))*s(k/2)
k为偶数时 s(k)=(1+a^(k/2))*s(k/2) 例如s(7)=a+(a+a^4)*s(3) s(6)=(1+a^3)*s(3) 有了二分的方法这题明显思路就清楚了
#include<cstdio> #include<cmath> #include<iostream> using namespace std; const int nMAX=35; int MAX; int M; typedef struct { long long m[nMAX][nMAX]; } Matrix; Matrix P,I; Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法 { int i,j,k; Matrix c; for (i = 0 ; i < MAX; i++) for (j = 0; j < MAX; j++) { c.m[i][j] = 0; for (k = 0; k < MAX; k++) c.m[i][j] += (a.m[i][k] * b.m[k][j])%M; c.m[i][j] %= M; } return c; } Matrix quickpow(long long n) { Matrix m = P, b = I; while (n >= 1) { if (n & 1) b = matrixmul(b,m); n = n >> 1; m = matrixmul(m,m); } return b; } Matrix add(Matrix a,Matrix b) { Matrix c; for(int i=0;i<MAX;i++) for(int j=0;j<MAX;j++) { c.m[i][j]=0; c.m[i][j]+=(a.m[i][j]+b.m[i][j])%M; } return c; } Matrix getsum(Matrix a,int k) { if(k==1) return a; Matrix t=getsum(a,k/2); if(k&1) return add(a,matrixmul(add(a,quickpow(k/2+1)),t)); return matrixmul(add(I,quickpow(k/2)),t); } int main() { long long k,m; Matrix ans; for(int i=0; i<nMAX; i++) for(int j=0; j<nMAX; j++) I.m[i][j]=i==j?1:0; while(~scanf("%d%d%d",&MAX,&k,&m)) { for(int i=0; i<MAX; i++) for(int j=0; j<MAX; j++) scanf("%d",&P.m[i][j]); M=m; ans=getsum(P,k); // for(int i=0;i<MAX;i++) // for(int j=0;j<MAX;j++) // ans.m[i][j]%=m; for(int i=0; i<MAX; i++) for(int j=0; j<MAX; j++) { if(j<MAX-1) printf("%d ",ans.m[i][j]); else printf("%d\n",ans.m[i][j]); } } return 0; }
最后更新:2017-04-04 07:03:38