矩阵专题

做了几个矩阵问题,总结一下。

矩阵是个很神奇的东西,有时候对于一个有规律的操作,需要执行很多次的时候,有时候可以构造矩阵很巧妙的解决。

另外对于递推式求解,可以通过构造矩阵巧妙解决。

经典的便是FIB数列,以及FIB数列的求和问题。

HDU 1575 Tr A

http://acm.hdu.edu.cn/showproblem.php?pid=1575

赤裸的矩阵快速幂乘

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 10  
  8. #define inf 1<<29  
  9. #define MOD 9973  
  10. #define LL long long  
  11. using namespace std;  
  12. struct Matrix{  
  13.     int m[N][N];  
  14. }init;  
  15. int n,k;  
  16. Matrix Mult(Matrix m1,Matrix m2){  
  17.     Matrix ans;  
  18.     for(int i=0;i<n;i++)  
  19.         for(int j=0;j<n;j++){  
  20.             ans.m[i][j]=0;  
  21.             for(int k=0;k<n;k++)  
  22.                 ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;  
  23.         }  
  24.     return ans;  
  25. }  
  26. Matrix Pow(Matrix m1,int b){  
  27.     Matrix ans;  
  28.     for(int i=0;i<n;i++)  
  29.         for(int j=0;j<n;j++)  
  30.             ans.m[i][j]=(i==j);  
  31.     while(b){  
  32.         if(b&1)  
  33.             ans=Mult(ans,m1);  
  34.         m1=Mult(m1,m1);  
  35.         b>>=1;  
  36.     }  
  37.     return ans;  
  38. }  
  39. int main(){  
  40.     int t;  
  41.     scanf("%d",&t);  
  42.     while(t--){  
  43.         scanf("%d%d",&n,&k);  
  44.         for(int i=0;i<n;i++)  
  45.             for(int j=0;j<n;j++)  
  46.                 scanf("%d",&init.m[i][j]);  
  47.         init=Pow(init,k);  
  48.         int ans=0;  
  49.         for(int i=0;i<n;i++)  
  50.             ans=(ans+init.m[i][i])%MOD;  
  51.         printf("%d\n",ans);  
  52.     }  
  53.     return 0;  
  54. }  

HDU 1588 Gauss Fibonacci

http://acm.hdu.edu.cn/showproblem.php?pid=1588

构造矩阵,通过矩阵乘法可以得到FIB数列的某一项,矩阵为{1,1,1,0}
其中这里要求的为
F(b)+F(k+b)+F(2*k+b)……
用矩阵表示即为A^b+A^(k+b)……,可以转化为A^b*(A^(0)+A^(k)……)
将K=A^k,即A^b*(K^0+K^1+K^2……),对于括号内部部分,有经典的二分解法,在Matrix67博客里面也有介绍

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 10  
  8. using namespace std;  
  9. struct Matrix{  
  10.     LL m[N][N];  
  11. }init,unit;  
  12. int MOD;  
  13. Matrix Mult(Matrix m1,Matrix m2,int n=2){  
  14.     Matrix ans;  
  15.     for(int i=0;i<n;i++)  
  16.         for(int j=0;j<n;j++){  
  17.             ans.m[i][j]=0;  
  18.             for(int k=0;k<n;k++)  
  19.                 ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;  
  20.         }  
  21.     return ans;  
  22. }  
  23. Matrix Pow(Matrix m1,int b,int n=2){  
  24.     Matrix ans;  
  25.     for(int i=0;i<n;i++)  
  26.         for(int j=0;j<n;j++)  
  27.             ans.m[i][j]=(i==j);  
  28.     while(b){  
  29.         if(b&1)  
  30.             ans=Mult(ans,m1,n);  
  31.         m1=Mult(m1,m1,n);  
  32.         b>>=1;  
  33.     }  
  34.     return ans;  
  35. }  
  36. Matrix Add(Matrix m1,Matrix m2,int n=2){  
  37.     Matrix ans;  
  38.     for(int i=0;i<n;i++)  
  39.         for(int j=0;j<n;j++)  
  40.             ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;  
  41.     return ans;  
  42. }  
  43. Matrix slove(Matrix init,int k,int n=2){  
  44.     if(k==1)  
  45.         return init;  
  46.     Matrix temp=slove(init,k>>1,n);  
  47.     temp=Add(temp,Mult(temp,Pow(init,k>>1)));  
  48.     if(k&1)  
  49.         return Add(temp,Pow(init,k));  
  50.     else  
  51.         return temp;  
  52. }  
  53. int main(){  
  54.     int k,b,n;  
  55.     while(scanf("%d%d%d%d",&k,&b,&n,&MOD)!=EOF){  
  56.         init.m[0][0]=init.m[0][1]=init.m[1][0]=1;  
  57.         init.m[1][1]=0;  
  58.         unit.m[0][0]=unit.m[1][1]=1;  
  59.         unit.m[1][0]=unit.m[0][1]=0;  
  60.         Matrix t;  
  61.         t=Pow(init,b);  
  62.         init=Pow(init,k);  
  63.         //init.m[0][1]即第k项fib,为A^k  
  64.         init=Add(unit,slove(init,n-1)); //B=A^k,   B^0+B^1+B^2……+B^n-1    
  65.         init=Mult(init,t);  
  66.         printf("%I64d\n",init.m[0][1]);  
  67.     }  
  68.     return 0;  
  69. }  


HDU 1757 A Simple Math Problem

http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?cid=1432&pid=1001&ojid=0

经典的构造矩阵解决递推式问题

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 10  
  8. #define inf 1<<29  
  9. //#define MOD 9973  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. struct Matrix{  
  16.     LL m[N][N];  
  17. }init,unit;  
  18. int MOD;  
  19. Matrix Mult(Matrix m1,Matrix m2,int n=10){  
  20.     Matrix ans;  
  21.     for(int i=0;i<n;i++)  
  22.         for(int j=0;j<n;j++){  
  23.             ans.m[i][j]=0;  
  24.             for(int k=0;k<n;k++)  
  25.                 ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;  
  26.         }  
  27.     return ans;  
  28. }  
  29. Matrix Pow(Matrix m1,int b,int n=10){  
  30.     Matrix ans;  
  31.     for(int i=0;i<n;i++)  
  32.         for(int j=0;j<n;j++)  
  33.             ans.m[i][j]=(i==j);  
  34.     while(b){  
  35.         if(b&1)  
  36.             ans=Mult(ans,m1,n);  
  37.         m1=Mult(m1,m1,n);  
  38.         b>>=1;  
  39.     }  
  40.     return ans;  
  41. }  
  42. Matrix Add(Matrix m1,Matrix m2,int n=10){  
  43.     Matrix ans;  
  44.     for(int i=0;i<n;i++)  
  45.         for(int j=0;j<n;j++)  
  46.             ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;  
  47.     return ans;  
  48. }  
  49. Matrix slove(Matrix init,int k,int n=10){  
  50.     if(k==1)  
  51.         return init;  
  52.     Matrix temp=slove(init,k>>1,n);  
  53.     temp=Add(temp,Mult(temp,Pow(init,k>>1)));  
  54.     if(k&1)  
  55.         return Add(temp,Pow(init,k));  
  56.     else  
  57.         return temp;  
  58. }  
  59. void debug(Matrix m1){  
  60.     for(int i=0;i<10;i++){  
  61.         for(int j=0;j<10;j++)  
  62.             printf("%d ",m1.m[i][j]);  
  63.         printf("\n");  
  64.     }  
  65. }  
  66. int main(){  
  67.     int k,b,n;  
  68.     int a[10];  
  69.     while(scanf("%d%d",&k,&MOD)!=EOF){  
  70.         for(int i=0;i<10;i++)  
  71.             scanf("%d",&a[i]);  
  72.         if(k<10)  
  73.             printf("%d\n",k);  
  74.         else{  
  75.             memset(init.m,0,sizeof(init.m));  
  76.             for(int i=0;i<10;i++)  
  77.                 init.m[i][0]=a[i];  
  78.             for(int i=1;i<10;i++)  
  79.                 init.m[i-1][i]=1;  
  80.             init=Pow(init,k-9);  
  81.             LL ans=0;  
  82.             for(int i=0;i<10;i++)  
  83.                 ans=(ans+(9-i)*init.m[i][0])%MOD;  
  84.             printf("%I64d\n",ans);  
  85.         }  
  86.     }  
  87.     return 0;  
  88. }  


HDU 2157 How many ways??

http://acm.hdu.edu.cn/showproblem.php?pid=2157

又是一个经典的应用 ,在离散数学中有讲,可达矩阵的K次幂便是从i到j走K步能到达的方案数

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 25  
  8. #define inf 1<<29  
  9. #define MOD 1000  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. struct Matrix{  
  16.     LL m[N][N];  
  17. }init,unit;  
  18. Matrix Mult(Matrix m1,Matrix m2,int n=10){  
  19.     Matrix ans;  
  20.     for(int i=0;i<n;i++)  
  21.         for(int j=0;j<n;j++){  
  22.             ans.m[i][j]=0;  
  23.             for(int k=0;k<n;k++)  
  24.                 ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;  
  25.         }  
  26.     return ans;  
  27. }  
  28. Matrix Pow(Matrix m1,int b,int n=10){  
  29.     Matrix ans;  
  30.     for(int i=0;i<n;i++)  
  31.         for(int j=0;j<n;j++)  
  32.             ans.m[i][j]=(i==j);  
  33.     while(b){  
  34.         if(b&1)  
  35.             ans=Mult(ans,m1,n);  
  36.         m1=Mult(m1,m1,n);  
  37.         b>>=1;  
  38.     }  
  39.     return ans;  
  40. }  
  41. Matrix Add(Matrix m1,Matrix m2,int n=10){  
  42.     Matrix ans;  
  43.     for(int i=0;i<n;i++)  
  44.         for(int j=0;j<n;j++)  
  45.             ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;  
  46.     return ans;  
  47. }  
  48. Matrix slove(Matrix init,int k,int n=10){  
  49.     if(k==1)  
  50.         return init;  
  51.     Matrix temp=slove(init,k>>1,n);  
  52.     temp=Add(temp,Mult(temp,Pow(init,k>>1)));  
  53.     if(k&1)  
  54.         return Add(temp,Pow(init,k));  
  55.     else  
  56.         return temp;  
  57. }  
  58. void debug(Matrix m1){  
  59.     for(int i=0;i<10;i++){  
  60.         for(int j=0;j<10;j++)  
  61.             printf("%d ",m1.m[i][j]);  
  62.         printf("\n");  
  63.     }  
  64. }  
  65. int main(){  
  66.     int n,m;  
  67.     while(scanf("%d%d",&n,&m)!=EOF&&n+m){  
  68.         memset(init.m,0,sizeof(init.m));  
  69.         int u,v,q,k;  
  70.         while(m--){           
  71.             scanf("%d%d",&u,&v);  
  72.             init.m[u][v]=1;  
  73.         }  
  74.         scanf("%d",&q);  
  75.         while(q--){  
  76.             scanf("%d%d%d",&u,&v,&k);  
  77.             Matrix unit=Pow(init,k,n);  
  78.             printf("%d\n",unit.m[u][v]);  
  79.         }  
  80.     }  
  81.     return 0;  
  82. }  


POJ 3233 Matrix Power Series

http://poj.org/problem?id=3233

经典矩阵二分,A^1+A^2+A^3……A^n,如果n为偶数A^1+A^2……A^n/2+A^(n/2)*(A^1+A^2……A^n/2)如果是奇数,就在最后再加一项A^n,这样就可以递归二分下去。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 35  
  8. #define inf 1<<29  
  9. //#define MOD 9973  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. struct Matrix{  
  16.     int m[N][N];  
  17. }init,unit;  
  18. int MOD;  
  19. Matrix Mult(Matrix m1,Matrix m2,int n){  
  20.     Matrix ans;  
  21.     for(int i=0;i<n;i++)  
  22.         for(int j=0;j<n;j++){  
  23.             ans.m[i][j]=0;  
  24.             for(int k=0;k<n;k++)  
  25.                 ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;  
  26.         }  
  27.     return ans;  
  28. }  
  29. Matrix Pow(Matrix m1,int b,int n){  
  30.     Matrix ans;  
  31.     for(int i=0;i<n;i++)  
  32.         for(int j=0;j<n;j++)  
  33.             ans.m[i][j]=(i==j);  
  34.     while(b){  
  35.         if(b&1)  
  36.             ans=Mult(ans,m1,n);  
  37.         m1=Mult(m1,m1,n);  
  38.         b>>=1;  
  39.     }  
  40.     return ans;  
  41. }  
  42. Matrix Add(Matrix m1,Matrix m2,int n){  
  43.     Matrix ans;  
  44.     for(int i=0;i<n;i++)  
  45.         for(int j=0;j<n;j++)  
  46.             ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;  
  47.     return ans;  
  48. }  
  49. Matrix slove(Matrix init,int k,int n){  
  50.     if(k==1)  
  51.         return init;  
  52.     Matrix temp=slove(init,k>>1,n);  
  53.     temp=Add(temp,Mult(temp,Pow(init,k>>1,n),n),n);  
  54.     if(k&1)  
  55.         return Add(temp,Pow(init,k,n),n);  
  56.     else  
  57.         return temp;  
  58. }  
  59. void debug(Matrix m1,int n){  
  60.     for(int i=0;i<n;i++){  
  61.         printf("%d",m1.m[i][0]);  
  62.         for(int j=1;j<n;j++)  
  63.             printf(" %d",m1.m[i][j]);  
  64.         printf("\n");  
  65.     }  
  66. }  
  67. int main(){  
  68.     int k,b,n;  
  69.     while(scanf("%d%d%d",&n,&k,&MOD)!=EOF){  
  70.         for(int i=0;i<n;i++)  
  71.             for(int j=0;j<n;j++){  
  72.                 scanf("%d",&init.m[i][j]);  
  73.                 init.m[i][j]%=MOD;  
  74.             }  
  75.         debug(slove(init,k,n),n);  
  76.     }  
  77.     return 0;  
  78. }  


ZOJ 3497 Mistwald

同样首先判断是否可达,如果K次不可达,则必然是False。如果K次只能到达目标点,则说明是实话,如果K次有多点可达,则说明是可能

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3497

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 30  
  8. #define inf 1<<29  
  9. //#define MOD 9973  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. struct Matrix{  
  16.     int m[N][N];  
  17. }init,unit;  
  18. Matrix Mult(Matrix m1,Matrix m2,int n){  
  19.     Matrix ans;  
  20.     for(int i=0;i<n;i++)  
  21.         for(int j=0;j<n;j++){  
  22.             ans.m[i][j]=0;  
  23.             for(int k=0;k<n;k++)  
  24.                 ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j]);  
  25.         }  
  26.     return ans;  
  27. }  
  28. Matrix Pow(Matrix m1,int b,int n){  
  29.     Matrix ans;  
  30.     for(int i=0;i<n;i++)  
  31.         for(int j=0;j<n;j++)  
  32.             ans.m[i][j]=(i==j);  
  33.     while(b){  
  34.         if(b&1)  
  35.             ans=Mult(ans,m1,n);  
  36.         m1=Mult(m1,m1,n);  
  37.         b>>=1;  
  38.     }  
  39.     return ans;  
  40. }  
  41. Matrix Add(Matrix m1,Matrix m2,int n){  
  42.     Matrix ans;  
  43.     for(int i=0;i<n;i++)  
  44.         for(int j=0;j<n;j++)  
  45.             ans.m[i][j]=(m1.m[i][j]+m2.m[i][j]);  
  46.     return ans;  
  47. }  
  48. int main(){  
  49.     int t,c,r;  
  50.     scanf("%d",&t);  
  51.     while(t--){  
  52.         scanf("%d%d",&r,&c);  
  53.         memset(init.m,0,sizeof(init.m));  
  54.         for(int i=0;i<r;i++){  
  55.             for(int j=0;j<c;j++){  
  56.                 int x1,x2,x3,x4,y1,y2,y3,y4;  
  57.                 getchar();  
  58.                 scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);    
  59.                 if(i==r-1&&j==c-1) continue;  
  60.                 init.m[i*c+j][(x1-1)*c+y1-1]=1;  
  61.                 init.m[i*c+j][(x2-1)*c+y2-1]=1;  
  62.                 init.m[i*c+j][(x3-1)*c+y3-1]=1;  
  63.                 init.m[i*c+j][(x4-1)*c+y4-1]=1;  
  64.             }  
  65.         }  
  66.         int q,k;  
  67.     //  for(int i=0;i<r*c;i++)  
  68.     //      init.m[i][i]=0;  
  69.         scanf("%d",&q);  
  70.         while(q--){  
  71.             scanf("%d",&k);  
  72.             Matrix tmp=Pow(init,k,r*c);   
  73.             if(tmp.m[0][r*c-1]==0){  
  74.                 puts("False");  
  75.                 continue;  
  76.             }  
  77.             int cnt=0;  
  78.             for(int i=0;i<r*c-1;i++)  
  79.                 if(tmp.m[0][i])  
  80.                     cnt++;  
  81.             if(!cnt)  
  82.                 puts("True");  
  83.             else  
  84.                 puts("Maybe");  
  85.         }  
  86.         puts("");  
  87.     }  
  88.     return 0;  
  89. }  


HDU 2807 The Shortest Path

http://acm.hdu.edu.cn/showproblem.php?pid=2807

没啥好说的,直接搞就行了。不过挺卡时间的,注意优化

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <iostream>  
  3. #define NN 81  
  4. #define inf 1<<29  
  5. using namespace std;  
  6. int n,m;  
  7. int matrix[NN][NN][NN];  
  8. int dis[NN][NN];  
  9. void init(){  
  10.      for(int i=1;i<=n;i++)   
  11.          for (int j=1; j<=m; j++)    
  12.              for (int k=1; k<=m; k++)            
  13.                  scanf("%d",&matrix[i][j][k]);  
  14. }  
  15.   
  16. void get_dis(){  
  17.      int temp[NN][NN];    
  18.      for (int a=1; a<=n; a++)    
  19.          for (int b=1; b<=n; b++)            
  20.              dis[a][b]=inf;       
  21.      for (int a=1; a<=n; a++)     
  22.          for (int b=1; b<=n; b++) {           
  23.              if(a==b) continue;        
  24.              for (int i=1; i<=m; i++){   
  25.                  for (int j=1; j<=m; j++){           
  26.                      temp[i][j]=0;               
  27.                      for (int k=1; k<=m; k++)           
  28.                      temp[i][j]+=matrix[a][i][k]*matrix[b][k][j];      
  29.                  }      
  30.              }  
  31.              for(int c=1; c<=n; c++){          
  32.                  if(a==c||b==c)  continue;                
  33.                  int flag=1;                      
  34.                  for (int i=1; i<=m && flag; i++)                 
  35.                      for (int j=1; j<=m && flag; j++)                                   
  36.                          if (temp[i][j]!=matrix[c][i][j]) flag=0;                        
  37.                  if (flag) dis[a][c]=1;                   
  38.              }      
  39.          }  
  40. }  
  41. void Floyed(){  
  42.      for(int k=1;k<=n;k++)     
  43.          for(int i=1;i<=n;i++)      
  44.              for(int j=1;j<=n;j++){       
  45.                  if (k==i || k==j || i==j) continue;             
  46.                  if (dis[i][j]>dis[i][k]+dis[k][j])              
  47.                      dis[i][j]=dis[i][k]+dis[k][j];        
  48.              }  
  49. }  
  50. void Query(){  
  51.      int t,x,y;  
  52.      scanf("%d",&t);  
  53.      while(t--){  
  54.            scanf("%d%d",&x,&y);  
  55.            if (dis[x][y]>=inf)   
  56.                printf("Sorry\n");  
  57.            else  
  58.                printf("%d\n",dis[x][y]);  
  59.      }  
  60. }  
  61. int main(){  
  62.     while(scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0){  
  63.         init();  
  64.         get_dis();  
  65.         Floyed();  
  66.         Query();  
  67.     }    
  68.     return 0;  
  69. }  



HDU 3483 A Very Simple Problem

http://acm.hdu.edu.cn/showproblem.php?pid=3483

贴个图,神构造,矩阵完美解决


[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 55  
  8. #define inf 1<<29  
  9. //#define MOD 9973  
  10. #define LL long long  
  11. #define eps 1e-7  
  12. #define zero(a) fabs(a)<eps  
  13. #define equal(a,b) zero(a-b)  
  14. using namespace std;  
  15. struct Matrix{  
  16.     LL m[N][N];  
  17. }init,unit;  
  18. LL MOD;  
  19. Matrix Mult(Matrix m1,Matrix m2,int n){  
  20.     Matrix ans;  
  21.     memset(ans.m,0,sizeof(ans.m));  
  22.     for(int k=0;k<n;k++)  
  23.         for(int i=0;i<n;i++)  
  24.             if(m1.m[i][k])  
  25.                 for(int j=0;j<n;j++){  
  26.                     ans.m[i][j]+=m1.m[i][k]*m2.m[k][j];  
  27.                     if(ans.m[i][j]>=MOD)ans.m[i][j]%=MOD;  
  28.                 }  
  29.     /*for(int i=0;i<n;i++) 
  30.         for(int j=0;j<n;j++){ 
  31.             ans.m[i][j]=0; 
  32.             for(int k=0;k<n;k++) 
  33.                 ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD; 
  34.         }*/  
  35.     return ans;  
  36. }  
  37. Matrix Pow(Matrix m1,int b,int n){  
  38.     Matrix ans;  
  39.     for(int i=0;i<n;i++)  
  40.         for(int j=0;j<n;j++)  
  41.             ans.m[i][j]=(i==j);  
  42.     while(b){  
  43.         if(b&1)  
  44.             ans=Mult(ans,m1,n);  
  45.         m1=Mult(m1,m1,n);  
  46.         b>>=1;  
  47.     }  
  48.     return ans;  
  49. }  
  50. Matrix Add(Matrix m1,Matrix m2,int n){  
  51.     Matrix ans;  
  52.     for(int i=0;i<n;i++)  
  53.         for(int j=0;j<n;j++)  
  54.             ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;  
  55.     return ans;  
  56. }  
  57. int n,x;  
  58. LL c[N][N];   
  59. int main(){  
  60.     while(scanf("%d%d%d",&n,&x,&MOD)!=EOF){  
  61.         if(n==-1&&x==-1&&MOD==-1) break;  
  62.         memset(init.m,0,sizeof(init.m));  
  63.         for(int i=0;i<=x;i++){  
  64.             c[i][0]=1;c[i][i]=1;  
  65.             for(int j=1;j<i;j++){  
  66.                 c[i][j]=(c[i-1][j]+c[i-1][j-1]);  
  67.                 if(c[i][j]>=MOD)  
  68.                     c[i][j]-=MOD;  
  69.             }  
  70.         }  
  71.         for(int j=0;j<=x;j++)  
  72.             for(int i=0;i<=j;i++)  
  73.                 init.m[i][j]=(c[j][i]*x)%MOD;  
  74.         for(int i=0;i<=x;i++)  
  75.             init.m[i][x+1]=(x*c[x][i])%MOD;  
  76.         init.m[x+1][x+1]=1;  
  77.         init=Pow(init,n-1,x+2);       
  78.         LL ans=0;  
  79.         for(int i=0;i<=x+1;i++)  
  80.             ans=(ans+(LL)x*init.m[i][x+1])%MOD;  
  81.         printf("%I64d\n",ans);  
  82.     }  
  83.     return 0;  
  84. }  

HDU 2276 Kiki & Little Kiki 2

每一个位置的状态ai=(ai+ai-1)%2,可以用异或加速

构造矩阵,便可解决

1 1 0 0 0 0 0

0 1 1 0 0 0 0 

0 0 1 1 0 0 0

0 0 0 1 1 0 0

0 0 0 0 1 1 0

0 0 0 0 0 1 1

1 0 0 0 0 0 1

http://acm.hdu.edu.cn/showproblem.php?pid=2276

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 105  
  8. #define inf 1<<29  
  9. #define MOD 9973  
  10. #define Max 301   
  11. #define LL long long  
  12. #define eps 1e-7  
  13. #define zero(a) fabs(a)<eps  
  14. #define equal(a,b) zero(a-b)  
  15. using namespace std;  
  16. struct Matrix{  
  17.     int m[N][N];  
  18. }init,unit;  
  19. int n,k;  
  20. Matrix Mult(Matrix m1,Matrix m2){  
  21.     Matrix ans;  
  22.     for(int i=0;i<n;i++)  
  23.         for(int j=0;j<n;j++){  
  24.             ans.m[i][j]=0;  
  25.             for(int k=0;k<n;k++)  
  26.                 ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%2;  
  27.         }  
  28.     return ans;  
  29. }  
  30. Matrix Pow(Matrix m1,int b){  
  31.     Matrix ans;  
  32.     for(int i=0;i<n;i++)  
  33.         for(int j=0;j<n;j++)  
  34.             ans.m[i][j]=(i==j);  
  35.     while(b){  
  36.         if(b&1)  
  37.             ans=Mult(ans,m1);  
  38.         m1=Mult(m1,m1);  
  39.         b>>=1;  
  40.     }  
  41.     return ans;  
  42. }  
  43. void debug(Matrix m1){  
  44.     for(int i=0;i<n;i++){  
  45.         for(int j=0;j<n;j++)  
  46.             printf("%d ",m1.m[i][j]);  
  47.         printf("\n");  
  48.     }  
  49. }  
  50. char str[N];  
  51. int main(){  
  52.     while(scanf("%d",&k)!=EOF){  
  53.         scanf("%s",str);  
  54.         n=strlen(str);  
  55.         memset(init.m,0,sizeof(init.m));  
  56.         for(int i=0;i<n;i++)  
  57.             init.m[i][i]=init.m[(i-1+n)%n][i]=1;  
  58.         init=Pow(init,k);  
  59.         //debug(init);  
  60.         for(int i=0;i<n;i++){  
  61.             int t=0;  
  62.             for(int j=0;j<n;j++)  
  63.                 t=t^((str[j]-'0')*init.m[j][i]);  
  64.             printf("%d",t);  
  65.         }  
  66.         puts("");  
  67.     }  
  68.     return 0;  
  69. }  

HDU 2855 Fibonacci Check-up

http://acm.hdu.edu.cn/showproblem.php?pid=2855

这个完全就是神构造,完全想不到,或者可以通过打表,打规律得到


[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #include<cstdio>  
  5. #include<cmath>  
  6. #include<algorithm>  
  7. #define N 2  
  8. using namespace std;  
  9. struct Matrix{  
  10.     int m[N][N];  
  11. }init,unit;  
  12. int n=2;  
  13. int MOD;  
  14. Matrix Mult(Matrix m1,Matrix m2){  
  15.     Matrix ans;  
  16.     memset(ans.m,0,sizeof(ans.m));  
  17.     for(int i=0;i<n;i++)  
  18.         for(int k=0;k<n;k++){  
  19.             if(m1.m[i][k])  
  20.                 for(int j=0;j<n;j++)                           
  21.                     ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%MOD;  
  22.         }  
  23.     return ans;  
  24. }  
  25. Matrix Pow(Matrix m1,int b){  
  26.     Matrix ans;  
  27.     for(int i=0;i<n;i++)  
  28.         for(int j=0;j<n;j++)  
  29.             ans.m[i][j]=(i==j);  
  30.     while(b){  
  31.         if(b&1)  
  32.             ans=Mult(ans,m1);  
  33.         m1=Mult(m1,m1);  
  34.         b>>=1;  
  35.     }  
  36.     return ans;  
  37. }  
  38. int main(){  
  39.     int t,k;  
  40.     scanf("%d",&t);  
  41.     while(t--){  
  42.         scanf("%d%d",&k,&MOD);  
  43.         if(k==0){  
  44.             printf("0\n");  
  45.             continue;  
  46.         }  
  47.         init.m[0][0]=init.m[0][1]=init.m[1][0]=1;  
  48.         init.m[1][1]=0;  
  49.         init=Pow(init,2*k-1);  
  50.         printf("%d\n",init.m[0][0]);  
  51.     }  
  52.     return 0;  
  53. }  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值