首页 > 代码库 > ACM 矩阵题目整理

ACM 矩阵题目整理

先从最基础的矩阵快速幂加速递推开始。

HDU 1005 Number Sequence

|f[n-2],f[n-1]|* |0 B| =|f[n-1], B*f[n-2]+A*f[n-1]|=|f[n-1],f[n]|

          |1 A|

建立矩阵如上然后利用快速幂求解即可。答案是mat[0][1]。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<queue>#include<cmath>#include<set>#include<string>#define INF 1000000005#define LL long longusing namespace std;const int MAXN =5;struct Matrix{    int n,m;    int a[MAXN][MAXN];    void clear(int x=0,int y=0)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }    Matrix operator * (const Matrix &b)const    {        Matrix tmp;        tmp.clear(n,b.m);        for(int i=0; i<n; ++i)            for(int j=0; j<b.m; ++j)                for(int k=0; k<m; ++k)                {                    tmp.a[i][j]+=a[i][k]*b.a[k][j];                    tmp.a[i][j]%=7;                }        return tmp;    }};Matrix quickPow(Matrix mat,int n){    Matrix res;    res.clear(2,2);    res.a[0][0]=res.a[1][1]=1;    while(n)    {        if(n&1) res=res*mat;        mat=mat*mat;        n=n>>1;    }    return res;}int main(){    int A,B,n;    while(scanf("%d%d%d",&A,&B,&n)!=EOF)    {        if(!A&&!B&&!n) break;        if(n==1||n==2)        {            puts("1");            continue;        }        Matrix mat;        mat.clear(2,2);        mat.a[0][0]=0;        mat.a[0][1]=B;        mat.a[1][0]=1;        mat.a[1][1]=A;        Matrix f;        f.clear(1,2);        f.a[0][0]=1;        f.a[0][1]=1;        n-=2;        Matrix s=f*quickPow(mat,n);        printf("%d\n",(s.a[0][1])%7);    }    return 0;}
View Code

 

HDU 4920 Matrix multiplication

矩阵乘法,直接算会超时。由于是模3,所以0很多,也就是稀疏矩阵。可以优化。

参见下文:http://www.cnblogs.com/jackiesteed/articles/2021604.html

#include<iostream>#include<vector>#include<map>#include<cmath>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<string>#define LL long longusing namespace std;int A[805][805],B[805][805];int C[805][805];int n;int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        for(int i=1; i<=n; ++i)            for(int j=1; j<=n; ++j)            {                scanf("%d",&A[i][j]);                A[i][j]%=3;            }        for(int i=1; i<=n; ++i)            for(int j=1; j<=n; ++j)            {                scanf("%d",&B[i][j]);                B[i][j]%=3;            }        memset(C,0,sizeof(C));        for(int i=1; i<=n; ++i)            for(int j=1; j<=n; ++j)            {                if(A[i][j]==0) continue;                for(int k=1; k<=n; ++k)                    C[i][k]+=A[i][j]*B[j][k];            }        for(int i=1; i<=n; ++i)        {            for(int j=1; j<=n; ++j)                if(j==1) printf("%d",C[i][j]%3);                else printf(" %d",C[i][j]%3);            printf("\n");        }    }    return 0;}
View Code

 

HDU 1575 Tr A

求矩阵的迹。直接快速幂即可。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<queue>#include<cmath>#include<set>#include<string>#define INF 1000000005#define LL long longusing namespace std;const int MAXN =12;struct Matrix{    int n,m;    int a[MAXN][MAXN];    void clear(int x=0,int y=0)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }    Matrix operator * (const Matrix &b)const    {        Matrix tmp;        tmp.clear(n,b.m);        for(int i=0; i<n; ++i)            for(int j=0; j<b.m; ++j)            {                for(int k=0; k<b.m; ++k)                {                    if(0==a[i][j]) continue;//优化!                    tmp.a[i][k]+=a[i][j]*b.a[j][k];                    tmp.a[i][k]%=9973;                }            }        return tmp;    }    void setOne(int x)    {        clear(x,x);        for(int i=0; i<x; ++i)            a[i][i]=1;    }};Matrix one;Matrix quickPow(Matrix mat,int n){    Matrix res=one;    while(n)    {        if(n&1) res=res*mat;        mat=mat*mat;        n=n>>1;    }    return res;}int main(){    int T;    scanf("%d",&T);    while(T--){        int n,k;        scanf("%d%d",&n,&k);        one.setOne(n);        Matrix mat;        mat.clear(n,n);        for(int i=0;i<n;++i)            for(int j=0;j<n;++j)            scanf("%d",&mat.a[i][j]);        mat=quickPow(mat,k);        int ans=0;        for(int i=0;i<n;++i)        {            ans+=mat.a[i][i];            ans%=9973;        }        printf("%d\n",ans);    }    return 0;}
View Code

 

HDU 1757 A Simple Math Problem

一个简单的递推,建立矩阵后,快速幂。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<queue>#include<cmath>#include<set>#include<string>#define INF 1000000005#define LL long longusing namespace std;const int MAXN =12;int M;struct Matrix{    int n,m;    int a[MAXN][MAXN];    void clear(int x=0,int y=0)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }    Matrix operator * (const Matrix &b)const    {        Matrix tmp;        tmp.clear(n,b.m);        for(int i=0; i<n; ++i)            for(int j=0; j<b.m; ++j)            {                for(int k=0; k<b.m; ++k)                {                    if(0==a[i][j]) continue;//优化!                    tmp.a[i][k]+=a[i][j]*b.a[j][k];                    tmp.a[i][k]%=M;                }            }        return tmp;    }    void setOne(int x)    {        clear(x,x);        for(int i=0; i<x; ++i)            a[i][i]=1;    }};Matrix one;Matrix quickPow(Matrix mat,int n){    Matrix res=one;    while(n)    {        if(n&1) res=res*mat;        mat=mat*mat;        n=n>>1;    }    return res;}int main(){    int k;    one.setOne(10);    while(scanf("%d%d",&k,&M)!=EOF)    {        Matrix mat;        mat.clear(10,10);        for(int i=0; i<9; ++i)            mat.a[i+1][i]=1;        for(int i=0; i<10; ++i)            scanf("%d",&mat.a[9-i][9]);        if(k<10) printf("%d\n",k%M);        else        {            Matrix f;            f.clear(1,10);            for(int i=0; i<10; ++i)                f.a[0][i]=i;            k-=9;            f=f*quickPow(mat,k);            printf("%d\n",f.a[0][9]);        }    }    return 0;}
View Code

 UVa 10870  Recurrences

与上面类型相似的题,建立矩阵,再快速幂加速。注意会超int。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<queue>#include<cmath>#include<set>#include<string>#define INF 1000000005#define LL long longusing namespace std;const int MAXN =20;int M;struct Matrix{    int n,m;    LL a[MAXN][MAXN];    void clear(int x=0,int y=0)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }    Matrix operator * (const Matrix &b)const    {        Matrix tmp;        tmp.clear(n,b.m);        for(int i=0; i<n; ++i)            for(int j=0; j<b.m; ++j)            {                for(int k=0; k<b.m; ++k)                {                    if(0==a[i][j]) continue;//优化!                    tmp.a[i][k]+=a[i][j]*b.a[j][k];                    tmp.a[i][k]%=M;                }            }        return tmp;    }    void setOne(int x)    {        clear(x,x);        for(int i=0; i<x; ++i)            a[i][i]=1;    }};Matrix one;Matrix quickPow(Matrix mat,LL n){    Matrix res=one;    while(n)    {        if(n&1) res=res*mat;        mat=mat*mat;        n=n>>1;    }    return res;}int main(){    int d,n;    while(scanf("%d%d%d",&d,&n,&M)!=EOF)    {        if(!d&&!n&&!M) break;        one.setOne(d);        Matrix mat;        mat.clear(d,d);        for(int i=0; i<d; ++i)            mat.a[i+1][i]=1;        for(int i=0; i<d; ++i)            scanf("%lld",&mat.a[d-1-i][d-1]);        Matrix f;        f.clear(1,d);        for(int i=0; i<d; ++i)            scanf("%lld",&f.a[0][i]);        if(n<=d)            printf("%lld\n",f.a[0][n-1]%M);        else        {            n-=d;            f=f*quickPow(mat,n);            printf("%lld\n",f.a[0][d-1]%M);        }    }    return 0;}
View Code

 

POJ 3734 Blocks

递推+矩阵快速幂。

设计状态的时候要考虑所有可能的情况,保证无重复无遗漏,再考虑转移。最后用矩阵加速。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<queue>#include<cmath>#include<set>#include<string>#define INF 1000000005#define LL long longusing namespace std;const int MAXN =4;int M=10007;struct Matrix{    int n,m;    int a[MAXN][MAXN];    Matrix(int x=0,int y=0):n(x),m(y)    {        memset(a,0,sizeof(a));    }    void clear(int x=0,int y=0)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }    Matrix operator * (const Matrix &b)const    {        Matrix tmp;        tmp.clear(n,b.m);        for(int i=0; i<n; ++i)            for(int j=0; j<b.m; ++j)            {                for(int k=0; k<b.m; ++k)                {                    if(0==a[i][j]) continue;//ÓÅ»¯£¡                    tmp.a[i][k]+=a[i][j]*b.a[j][k];                    tmp.a[i][k]%=M;                }            }        return tmp;    }    void setOne(int x)    {        clear(x,x);        for(int i=0; i<x; ++i)            a[i][i]=1;    }};Matrix one;Matrix quickPow(Matrix mat,int n){    Matrix res=one;    while(n)    {        if(n&1) res=res*mat;        mat=mat*mat;        n=n>>1;    }    return res;}int main(){    one.setOne(3);    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        Matrix mat(3,3);        mat.a[0][0]=2,mat.a[0][1]=1,mat.a[0][2]=0;        mat.a[1][0]=2,mat.a[1][1]=2,mat.a[1][2]=2;        mat.a[2][0]=0,mat.a[2][1]=1,mat.a[2][2]=2;        Matrix f(3,1);        f.a[0][0]=1;        Matrix ans=f*quickPow(mat,n);        printf("%d\n",ans.a[0][0]);    }    return 0;}
View Code