矩阵专题小结

来源:互联网 发布:弗莱彻级驱逐舰数据 编辑:程序博客网 时间:2024/05/18 01:39

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

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

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

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

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

HDU 1575 Tr A

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

赤裸的矩阵快速幂乘

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 10#define inf 1<<29#define MOD 9973#define LL long longusing namespace std;struct Matrix{int m[N][N];}init;int n,k;Matrix Mult(Matrix m1,Matrix m2){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}return ans;}Matrix Pow(Matrix m1,int b){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1);m1=Mult(m1,m1);b>>=1;}return ans;}int main(){int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&k);for(int i=0;i<n;i++)for(int j=0;j<n;j++)scanf("%d",&init.m[i][j]);init=Pow(init,k);int ans=0;for(int i=0;i<n;i++)ans=(ans+init.m[i][i])%MOD;printf("%d\n",ans);}return 0;}

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博客里面也有介绍

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 10using namespace std;struct Matrix{LL m[N][N];}init,unit;int MOD;Matrix Mult(Matrix m1,Matrix m2,int n=2){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}return ans;}Matrix Pow(Matrix m1,int b,int n=2){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n=2){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;return ans;}Matrix slove(Matrix init,int k,int n=2){if(k==1)return init;Matrix temp=slove(init,k>>1,n);    temp=Add(temp,Mult(temp,Pow(init,k>>1)));if(k&1)return Add(temp,Pow(init,k));elsereturn temp;}int main(){int k,b,n;while(scanf("%d%d%d%d",&k,&b,&n,&MOD)!=EOF){init.m[0][0]=init.m[0][1]=init.m[1][0]=1;init.m[1][1]=0;unit.m[0][0]=unit.m[1][1]=1;unit.m[1][0]=unit.m[0][1]=0;Matrix t;t=Pow(init,b);init=Pow(init,k);//init.m[0][1]即第k项fib,为A^kinit=Add(unit,slove(init,n-1)); //B=A^k,   B^0+B^1+B^2……+B^n-1init=Mult(init,t);    printf("%I64d\n",init.m[0][1]);}return 0;}


HDU 1757 A Simple Math Problem

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

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

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 10#define inf 1<<29//#define MOD 9973#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{LL m[N][N];}init,unit;int MOD;Matrix Mult(Matrix m1,Matrix m2,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}return ans;}Matrix Pow(Matrix m1,int b,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;return ans;}Matrix slove(Matrix init,int k,int n=10){if(k==1)return init;Matrix temp=slove(init,k>>1,n);    temp=Add(temp,Mult(temp,Pow(init,k>>1)));if(k&1)return Add(temp,Pow(init,k));elsereturn temp;}void debug(Matrix m1){for(int i=0;i<10;i++){for(int j=0;j<10;j++)printf("%d ",m1.m[i][j]);printf("\n");}}int main(){int k,b,n;int a[10];while(scanf("%d%d",&k,&MOD)!=EOF){for(int i=0;i<10;i++)scanf("%d",&a[i]);if(k<10)printf("%d\n",k);else{memset(init.m,0,sizeof(init.m));for(int i=0;i<10;i++)init.m[i][0]=a[i];for(int i=1;i<10;i++)init.m[i-1][i]=1;init=Pow(init,k-9);LL ans=0;for(int i=0;i<10;i++)ans=(ans+(9-i)*init.m[i][0])%MOD;printf("%I64d\n",ans);}}return 0;}


HDU 2157 How many ways??

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

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

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 25#define inf 1<<29#define MOD 1000#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{LL m[N][N];}init,unit;Matrix Mult(Matrix m1,Matrix m2,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}return ans;}Matrix Pow(Matrix m1,int b,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n=10){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;return ans;}Matrix slove(Matrix init,int k,int n=10){if(k==1)return init;Matrix temp=slove(init,k>>1,n);    temp=Add(temp,Mult(temp,Pow(init,k>>1)));if(k&1)return Add(temp,Pow(init,k));elsereturn temp;}void debug(Matrix m1){for(int i=0;i<10;i++){for(int j=0;j<10;j++)printf("%d ",m1.m[i][j]);printf("\n");}}int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF&&n+m){memset(init.m,0,sizeof(init.m));int u,v,q,k;while(m--){scanf("%d%d",&u,&v);init.m[u][v]=1;}scanf("%d",&q);while(q--){scanf("%d%d%d",&u,&v,&k);Matrix unit=Pow(init,k,n);printf("%d\n",unit.m[u][v]);}}return 0;}


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,这样就可以递归二分下去。

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 35#define inf 1<<29//#define MOD 9973#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{int m[N][N];}init,unit;int MOD;Matrix Mult(Matrix m1,Matrix m2,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}return ans;}Matrix Pow(Matrix m1,int b,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;return ans;}Matrix slove(Matrix init,int k,int n){if(k==1)return init;Matrix temp=slove(init,k>>1,n);    temp=Add(temp,Mult(temp,Pow(init,k>>1,n),n),n);if(k&1)return Add(temp,Pow(init,k,n),n);elsereturn temp;}void debug(Matrix m1,int n){for(int i=0;i<n;i++){printf("%d",m1.m[i][0]);for(int j=1;j<n;j++)printf(" %d",m1.m[i][j]);printf("\n");}}int main(){int k,b,n;while(scanf("%d%d%d",&n,&k,&MOD)!=EOF){for(int i=0;i<n;i++)for(int j=0;j<n;j++){scanf("%d",&init.m[i][j]);init.m[i][j]%=MOD;}    debug(slove(init,k,n),n);}return 0;}


ZOJ 3497 Mistwald

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

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

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 30#define inf 1<<29//#define MOD 9973#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{int m[N][N];}init,unit;Matrix Mult(Matrix m1,Matrix m2,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j]);}return ans;}Matrix Pow(Matrix m1,int b,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(m1.m[i][j]+m2.m[i][j]);return ans;}int main(){int t,c,r;scanf("%d",&t);while(t--){scanf("%d%d",&r,&c);memset(init.m,0,sizeof(init.m));for(int i=0;i<r;i++){for(int j=0;j<c;j++){int x1,x2,x3,x4,y1,y2,y3,y4;getchar();scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);  if(i==r-1&&j==c-1) continue;init.m[i*c+j][(x1-1)*c+y1-1]=1;init.m[i*c+j][(x2-1)*c+y2-1]=1;init.m[i*c+j][(x3-1)*c+y3-1]=1;init.m[i*c+j][(x4-1)*c+y4-1]=1;}}int q,k;//for(int i=0;i<r*c;i++)//init.m[i][i]=0;scanf("%d",&q);while(q--){scanf("%d",&k);Matrix tmp=Pow(init,k,r*c);if(tmp.m[0][r*c-1]==0){puts("False");continue;}int cnt=0;for(int i=0;i<r*c-1;i++)if(tmp.m[0][i])cnt++;if(!cnt)puts("True");elseputs("Maybe");}puts("");}return 0;}


HDU 2807 The Shortest Path

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

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

#include <cstdio>#include <iostream>#define NN 81#define inf 1<<29using namespace std;int n,m;int matrix[NN][NN][NN];int dis[NN][NN];void init(){     for(int i=1;i<=n;i++)          for (int j=1; j<=m; j++)               for (int k=1; k<=m; k++)                           scanf("%d",&matrix[i][j][k]);}void get_dis(){     int temp[NN][NN];       for (int a=1; a<=n; a++)           for (int b=1; b<=n; b++)                       dis[a][b]=inf;          for (int a=1; a<=n; a++)            for (int b=1; b<=n; b++) {                      if(a==b) continue;                   for (int i=1; i<=m; i++){                  for (int j=1; j<=m; j++){                              temp[i][j]=0;                                  for (int k=1; k<=m; k++)                              temp[i][j]+=matrix[a][i][k]*matrix[b][k][j];                     }                 }             for(int c=1; c<=n; c++){                         if(a==c||b==c)  continue;                               int flag=1;                                     for (int i=1; i<=m && flag; i++)                                    for (int j=1; j<=m && flag; j++)                                                          if (temp[i][j]!=matrix[c][i][j]) flag=0;                                       if (flag) dis[a][c]=1;                              }             }}void Floyed(){     for(int k=1;k<=n;k++)            for(int i=1;i<=n;i++)                 for(int j=1;j<=n;j++){                      if (k==i || k==j || i==j) continue;                            if (dis[i][j]>dis[i][k]+dis[k][j])                                 dis[i][j]=dis[i][k]+dis[k][j];                   }}void Query(){     int t,x,y;     scanf("%d",&t);     while(t--){           scanf("%d%d",&x,&y);           if (dis[x][y]>=inf)                printf("Sorry\n");           else               printf("%d\n",dis[x][y]);     }}int main(){    while(scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0){        init();        get_dis();        Floyed();        Query();    }      return 0;}



HDU 3483 A Very Simple Problem

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

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


#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 55#define inf 1<<29//#define MOD 9973#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{LL m[N][N];}init,unit;LL MOD;Matrix Mult(Matrix m1,Matrix m2,int n){Matrix ans;memset(ans.m,0,sizeof(ans.m));for(int k=0;k<n;k++)        for(int i=0;i<n;i++)            if(m1.m[i][k])                for(int j=0;j<n;j++){                    ans.m[i][j]+=m1.m[i][k]*m2.m[k][j];                    if(ans.m[i][j]>=MOD)ans.m[i][j]%=MOD;                }/*for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;}*/return ans;}Matrix Pow(Matrix m1,int b,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1,n);m1=Mult(m1,m1,n);b>>=1;}return ans;}Matrix Add(Matrix m1,Matrix m2,int n){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;return ans;}int n,x;LL c[N][N];int main(){while(scanf("%d%d%d",&n,&x,&MOD)!=EOF){if(n==-1&&x==-1&&MOD==-1) break;memset(init.m,0,sizeof(init.m));for(int i=0;i<=x;i++){    c[i][0]=1;c[i][i]=1;    for(int j=1;j<i;j++){    c[i][j]=(c[i-1][j]+c[i-1][j-1]);if(c[i][j]>=MOD)c[i][j]-=MOD;}    }for(int j=0;j<=x;j++)for(int i=0;i<=j;i++)init.m[i][j]=(c[j][i]*x)%MOD;for(int i=0;i<=x;i++)init.m[i][x+1]=(x*c[x][i])%MOD;init.m[x+1][x+1]=1;init=Pow(init,n-1,x+2);LL ans=0;for(int i=0;i<=x+1;i++)ans=(ans+(LL)x*init.m[i][x+1])%MOD;printf("%I64d\n",ans);}return 0;}

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

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 105#define inf 1<<29#define MOD 9973#define Max 301#define LL long long#define eps 1e-7#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)using namespace std;struct Matrix{int m[N][N];}init,unit;int n,k;Matrix Mult(Matrix m1,Matrix m2){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ans.m[i][j]=0;for(int k=0;k<n;k++)ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%2;}return ans;}Matrix Pow(Matrix m1,int b){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1);m1=Mult(m1,m1);b>>=1;}return ans;}void debug(Matrix m1){for(int i=0;i<n;i++){for(int j=0;j<n;j++)printf("%d ",m1.m[i][j]);printf("\n");}}char str[N];int main(){while(scanf("%d",&k)!=EOF){scanf("%s",str);n=strlen(str);memset(init.m,0,sizeof(init.m));for(int i=0;i<n;i++)init.m[i][i]=init.m[(i-1+n)%n][i]=1;init=Pow(init,k);//debug(init);for(int i=0;i<n;i++){int t=0;for(int j=0;j<n;j++)t=t^((str[j]-'0')*init.m[j][i]);printf("%d",t);}puts("");}return 0;}

HDU 2855 Fibonacci Check-up

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

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


#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 2using namespace std;struct Matrix{int m[N][N];}init,unit;int n=2;int MOD;Matrix Mult(Matrix m1,Matrix m2){Matrix ans;memset(ans.m,0,sizeof(ans.m));for(int i=0;i<n;i++)for(int k=0;k<n;k++){if(m1.m[i][k])    for(int j=0;j<n;j++) ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%MOD;}return ans;}Matrix Pow(Matrix m1,int b){Matrix ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans.m[i][j]=(i==j);while(b){if(b&1)ans=Mult(ans,m1);m1=Mult(m1,m1);b>>=1;}return ans;}int main(){int t,k;scanf("%d",&t);while(t--){scanf("%d%d",&k,&MOD);if(k==0){printf("0\n");continue;}init.m[0][0]=init.m[0][1]=init.m[1][0]=1;init.m[1][1]=0;init=Pow(init,2*k-1);printf("%d\n",init.m[0][0]);}return 0;}




原创粉丝点击