UVA-11149 Power of Matrix(矩阵二分幂)
题目大意:给一个n阶方阵,求A1+A2+A3+......Ak。
题目分析:令F(k)=A1+A2+A3+......Ak。当k为偶数时,F(k)=F(k/2)*(E+Ak/2),k为奇数时,F(k)=F(k/2)*(E+Ak/2)+Ak。证明这两条公式也很简单,把这两条公式展开就行了。根据公式,递归即可。
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<cstring> 4 # include<algorithm> 5 using namespace std; 6 struct matrix 7 { 8 int r,c,m[45][45]; 9 matrix(int _r,int _c):r(_r),c(_c){} 10 }; 11 matrix multiply(matrix a,matrix b) 12 { 13 matrix c(a.r,b.c); 14 for(int i=1;i<=c.r;++i){ 15 for(int j=1;j<=c.c;++j){ 16 c.m[i][j]=0; 17 for(int k=1;k<=a.c;++k){ 18 c.m[i][j]+=(a.m[i][k]%10)*(b.m[k][j]%10); 19 c.m[i][j]%=10; 20 } 21 } 22 } 23 return c; 24 } 25 matrix mypow(matrix a,int n) 26 { 27 if(n==0){ 28 for(int i=1;i<=a.r;++i) 29 for(int j=1;j<=a.c;++j) 30 a.m[i][j]=(i==j)?1:0; 31 return a; 32 } 33 if(n==1) 34 return a; 35 matrix res=mypow(a,n/2); 36 res=multiply(res,res); 37 if(n&1) 38 res=multiply(res,a); 39 return res; 40 } 41 matrix add(matrix a,matrix b) 42 { 43 for(int i=1;i<=a.r;++i) 44 for(int j=1;j<=a.c;++j){ 45 a.m[i][j]+=b.m[i][j]; 46 a.m[i][j]%=10;///忘记取模,WA很多次。 47 } 48 return a; 49 } 50 matrix work(matrix mat,int k) 51 { 52 if(k==0){ 53 for(int i=1;i<=mat.r;++i) 54 for(int j=1;j<=mat.c;++j) 55 mat.m[i][j]=(i==j)?1:0; 56 return mat; 57 } 58 if(k==1) 59 return mat; 60 matrix res=work(mat,k/2); 61 matrix one(mat.r,mat.c); 62 for(int i=1;i<=one.r;++i) 63 for(int j=1;j<=one.c;++j) 64 one.m[i][j]=(i==j)?1:0; 65 one=add(one,mypow(mat,k/2)); 66 res=multiply(res,one); 67 if(k&1) 68 res=add(res,mypow(mat,k)); 69 return res; 70 } 71 int main() 72 { 73 int n,k; 74 while(scanf("%d%d",&n,&k)&&n) 75 { 76 matrix mat(n,n); 77 for(int i=1;i<=n;++i){ 78 for(int j=1;j<=n;++j){ 79 scanf("%d",&mat.m[i][j]); 80 mat.m[i][j]%=10; 81 } 82 } 83 matrix ans=work(mat,k); 84 for(int i=1;i<=ans.r;++i){ 85 printf("%d",ans.m[i][1]); 86 for(int j=2;j<=ans.c;++j) 87 printf(" %d",ans.m[i][j]); 88 printf("\n");///没注意格式,WA很多次!!! 89 } 90 printf("\n"); 91 } 92 return 0; 93 }