矩阵小结

来源:互联网 发布:mac php protobuf 编辑:程序博客网 时间:2024/06/16 08:19

前沿:之前之做过一些递推关系式简单的矩阵快速幂,看了大牛的博客发现对于那种方程两边有多个不同的未知变量也可以用矩阵解决:http://blog.csdn.net/abcjennifer/article/details/5302198,于是找了几道题练手,顺便分享一下经验。

 

题目链接:http://acm.fzu.edu.cn/problem.php?pid=1683

思路:直接给出递推关系式:S(n)=S(n-1)+F(n)=S(n-1)+3*F(n-1)+2*F(n-2)+7*F(n-3).于是写成矩阵的形式:

从而求的S(n).

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MOD=2009; 7  8 int n; 9 struct Matrix{10     int map[4][4];11 }Mata,Matb;12 13 void Initiate()14 {15     for(int i=0;i<4;i++)16         for(int j=0;j<4;j++)17             Mata.map[i][j]=0;18     Mata.map[0][0]=1,Mata.map[0][1]=3;19     Mata.map[0][2]=2,Mata.map[0][3]=7;20 21     Mata.map[1][1]=3,Mata.map[1][2]=2;22     Mata.map[1][3]=7;23 24     Mata.map[2][1]=Mata.map[3][2]=1;25 }26 27 28 Matrix Mul(const Matrix &a,const Matrix &b)29 {30     Matrix c;31     for(int i=0;i<4;i++){32         for(int j=0;j<4;j++){33             c.map[i][j]=0;34             for(int k=0;k<4;k++){35                 c.map[i][j]+=a.map[i][k]*b.map[k][j];36                 c.map[i][j]%=MOD;37             }38         }39     }40     return c;41 }42 43 Matrix Pow(Matrix &q,int n)44 {45     Matrix p;46     for(int i=0;i<4;i++)47         for(int j=0;j<4;j++)48             p.map[i][j]=(i==j)?1:0;49     while(n){50         if(n&1){51             p=Mul(p,q);52         }53         n>>=1;54         q=Mul(q,q);55     }56     return p;57 }58 59 int main()60 {61     int _case,t=1;62     scanf("%d",&_case);63     while(_case--){64         scanf("%d",&n);65         printf("Case %d: ",t++);66         if(n==0)puts("1");67         else if(n==1)puts("4");68         else if(n==2)puts("9");69         else {70             Initiate();71             Matb=Pow(Mata,n-2);72             printf("%d\n",(Matb.map[0][0]*9+Matb.map[0][1]*5+Matb.map[0][2]*3+Matb.map[0][3]*1)%MOD);73         }74     }75     return 0;76 }
View Code

 

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2117

思路:设a(n)表示n位数且7、9的出现的个数均为偶数的组数,b(n)表示7出现偶数次,9出现奇数次的组数,c(n)表示7出现奇数次,9出现偶数次的组数,d(n)表示7、9均出现奇数次的组数,于是有下列递推关系式:

a(n)=3*a(n-1)+b(n-1)+c(n-1);

b(n)=a(n-1)+3*b(n-1)+d(n-1);

c(n)=a(n-1)+3*c(n-1)+d(n-1);

d(n)=b(n-1)+c(n-1)+3*d(n-1);

于是可以构造矩阵:

[3,1,1,0]    [a(n-1)]       [a(n)]

[1,3,0,1]    [b(n-1)]   =  [b(n]

[1,0,3,1]    [c(n-1)]       [c(n)]

[0,1,1,3]    [d(n-1)]       d[(n)]

从而矩阵快速幂求a(n)即可。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MOD=1000000007; 7  8 long long n; 9 struct Matrix{10     long long map[4][4];11 }Mata,Matb;12 13 14 void Initiate()15 {16     Mata.map[0][0]=3,Mata.map[0][1]=1;17     Mata.map[0][2]=1,Mata.map[0][3]=0;18 19     Mata.map[1][0]=1,Mata.map[1][1]=3;20     Mata.map[1][2]=0,Mata.map[1][3]=1;21 22     Mata.map[2][0]=1,Mata.map[2][1]=0;23     Mata.map[2][2]=3,Mata.map[2][3]=1;24 25     Mata.map[3][0]=0,Mata.map[3][1]=1;26     Mata.map[3][2]=1,Mata.map[3][3]=3;27 }28 29 Matrix Mul(const Matrix &a,const Matrix &b)30 {31     Matrix c;32     for(int i=0;i<4;i++){33         for(int j=0;j<4;j++){34             c.map[i][j]=0;35             for(int k=0;k<4;k++){36                 c.map[i][j]+=a.map[i][k]*b.map[k][j];37                 c.map[i][j]%=MOD;38             }39         }40     }41     return c;42 }43 44 Matrix Pow(Matrix q,long long  n)45 {46     Matrix p;47     for(int i=0;i<4;i++)48         for(int j=0;j<4;j++)49             p.map[i][j]=(i==j)?1:0;50     while(n){51         if(n&1){52             p=Mul(p,q);53         }54         n>>=1;55         q=Mul(q,q);56     }57     return p;58 }59 60 61 int main()62 {63     Initiate();64     int _case;65     scanf("%d",&_case);66     while(_case--){67         scanf("%I64d",&n);68         if(n==1)puts("3");69         else {70             Matb=Pow(Mata,n-1);71         //    cout<<Matb.map[0][0]<<"**"<<Matb.map[0][1]<<"**"<<Matb.map[0][2]<<endl;72             long long ans=(Matb.map[0][0]*3+Matb.map[0][1]*1+Matb.map[0][2]*1)%MOD;73             printf("%I64d\n",ans);74         }75     }76     return 0;77 }
View Code

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3306

思路:这道题与前几道有所不同,辅助矩阵不定,不过也好办。

这里直接给出递推式:S(n)=S(n-1)+A(n)^2=S(n-1)+x^2*A(n-1)^2+y^2*A(n-2)^2+2*x*y*A(n-1)*A(n-2);

于是构造矩阵:

| S(n)           |      | 1  X^2  Y^2  2XY |     | S(n-1)           |
| A(n)^2       | =   | 0  x^2  Y^2  2XY |     | A(n-1)^2       |
| A(n-1)^2    |      | 0  1      0      0     |     | A(n-2)^2       |
| A(n)A(n-1) |       | 0   X     0      Y    |      | A(n-1)A(n-2) |

于是就可以用矩阵快速幂求解S(n)了。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MOD 10007 7  8 struct Matrix{ 9     int map[4][4];10 }Mata,Matb;11 12 void Initiate(int x,int y)13 {14     for(int i=0;i<4;i++)15         for(int j=0;j<4;j++)16             Mata.map[i][j]=0;17     Mata.map[0][0]=1,Mata.map[0][1]=(x*x)%MOD;18     Mata.map[0][2]=(y*y)%MOD,Mata.map[0][3]=(2*x*y)%MOD;19 20     Mata.map[1][1]=(x*x)%MOD;Mata.map[1][2]=(y*y)%MOD;21     Mata.map[1][3]=(2*x*y)%MOD;22 23     Mata.map[2][1]=1;24 25     Mata.map[3][1]=x,Mata.map[3][3]=y;26 }27     28 Matrix Mul(const Matrix &a,const Matrix &b)29 {30     Matrix c;31     for(int i=0;i<4;i++){32         for(int j=0;j<4;j++){33             c.map[i][j]=0;34             for(int k=0;k<4;k++){35                 c.map[i][j]+=a.map[i][k]*b.map[k][j];36                 c.map[i][j]%=MOD;37             }38         }39     }40     return c;41 }42 43 Matrix Pow(Matrix q,int n)44 {45     Matrix p;46     for(int i=0;i<4;i++)47         for(int j=0;j<4;j++)48             p.map[i][j]=(i==j)?1:0;49     while(n){50         if(n&1){51             p=Mul(p,q);52         }53         n>>=1;54         q=Mul(q,q);55     }56     return p;57 }58 59 int main()60 {61     int n,x,y,sum;62     while(~scanf("%d%d%d",&n,&x,&y)){63         x%=MOD,y%=MOD;64         if(n==2){65             sum=1+1+((x+y)%MOD*(x+y)%MOD)%MOD;66             printf("%d\n",sum);67         }else {68             Initiate(x,y);69             Matb=Pow(Mata,n-1);70 //            cout<<Matb.map[0][0]<<"**"<<Matb.map[0][1]<<"**"<<Matb.map[0][2]<<"**"<<Matb.map[0][3]<<endl;71             sum=(2*Matb.map[0][0]+1*Matb.map[0][1]+1*Matb.map[0][2]+1*Matb.map[0][3])%MOD;72             printf("%d\n",sum);73         }74     }75     return 0;76 }
View Code

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4686

思路:与上一题类似,直接给出递推式:S(n)=S(n-1)+F(n-1)*G(n-1)=S(n-1)+ax*bx*F(n-2)*G(n-2)+ax*by*F(n-2)+ay*bx*G(n-2)+ay*by。

于是构造矩阵:

[ 1,ax*bx,ax*by,ay*bx,ay*by]     [      S(n-1)         ]        [     S(n)             ]

[ 0,ax*bx,ax*by,ay*bx,ay*by]     [  F(n-2)*G(n-2) ]        [  F(n-1)*G(n-1) ]

[ 0,     0,     ax,       0,      ay]     [    F(n-2)           ]  =    [    F(n-1)           ]

[ 0,     0,      0,       bx,     by]     [   G(n-2)           ]        [    G(n-1)           ]

[ 0,     0,      0,        0,       1]     [        1               ]        [        1               ]

从而矩阵快速幂求出S(n);

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MOD 1000000007 7 typedef long long ll; 8  9 struct Matrix{10     ll map[5][5];11 }Mata,Matb;12 13 void Initiate(ll ax,ll ay,ll bx,ll by)14 {15     for(int i=0;i<5;i++)16         for(int j=0;j<5;j++)17             Mata.map[i][j]=0;18     Mata.map[0][0]=1,Mata.map[0][1]=ax*bx%MOD;19     Mata.map[0][2]=ax*by%MOD,Mata.map[0][3]=ay*bx%MOD;20     Mata.map[0][4]=ay*by%MOD;21 22     Mata.map[1][1]=ax*bx%MOD,Mata.map[1][2]=ax*by%MOD;23     Mata.map[1][3]=ay*bx%MOD,Mata.map[1][4]=ay*by%MOD;24 25     Mata.map[2][2]=ax,Mata.map[2][4]=ay;26 27     Mata.map[3][3]=bx,Mata.map[3][4]=by;28 29     Mata.map[4][4]=1;30     /*31     for(int i=0;i<5;i++){32         for(int j=0;j<5;j++){33             cout<<Mata.map[i][j]<<" ";34         }35         cout<<endl;36     }*/37 }38 39 Matrix Mul(const Matrix &a,const Matrix &b)40 {41     Matrix c;42     for(int i=0;i<5;i++){43         for(int j=0;j<5;j++){44             c.map[i][j]=0;45             for(int k=0;k<5;k++){46                 c.map[i][j]+=a.map[i][k]*b.map[k][j];47                 c.map[i][j]%=MOD;48             }49         }50     }51     return c;52 }53 54 Matrix Pow(Matrix q,ll n)55 {56     Matrix p;57     for(int i=0;i<5;i++)58         for(int j=0;j<5;j++)59             p.map[i][j]=(i==j)?1:0;60     while(n){61         if(n&1){62             p=Mul(p,q);63         }64         n>>=1;65         q=Mul(q,q);66     }67     return p;68 }69 70 71 int main()72 {73    // freopen("1.txt","r",stdin);74     ll n,a0,ax,ay,b0,bx,by,sum,sum1;75     while(~scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&n,&a0,&ax,&ay,&b0,&bx,&by)){76         if(n==0)puts("0");77         else if(n==1){78             sum=(a0*b0)%MOD;79             printf("%I64d\n",sum);80         }else {81             Initiate(ax,ay,bx,by);82             Matb=Pow(Mata,n-1);83             sum1=(a0*b0)%MOD;84         //    cout<<Matb.map[0][0]<<"**"<<Matb.map[0][1]<<"***"<<Matb.map[0][2]<<"***"<<Matb.map[0][3]<<"**"<<Matb.map[0][4]<<endl;85             sum=(sum1*Matb.map[0][0]%MOD+(a0*b0%MOD)*Matb.map[0][1]%MOD+(a0*Matb.map[0][2]%MOD)+(b0*Matb.map[0][3]%MOD)+Matb.map[0][4])%MOD;86             printf("%I64d\n",sum);87         }88     }89     return 0;90 }
View Code

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2971

思路:与上一道类似,直接给出递推式:S(n)=S(n-1)+F(n)^2=S(n-1)+4*x*x*F(n-1)^2-4*x*F(n-1)*F(n-2)+F(n-2)^2。

于是构造矩阵:

[1,4*x*x,-4*x,1]   [S(n-1)           ]          [S(n)           ]

[0,4*x*x,-4*x,1]   [F(n-1)^2       ]     =   [F(n)^2        ]

[0, 2*x,  -1,   0]   [F(n-1)*F(n-2)]          [F(n)*F(n-1)]

[0,   1,    0,   0]   [F(n-2)^2        ]         [F(n-1)^2     ]

从而矩阵快速幂求出S(n)。

PS:这里由于有负数出现,取模的时候得小心。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7  8 ll n,x,m,sum; 9 struct Matrix{10     ll map[4][4];11 }Mata,Matb;12 13 void Initiate(ll x)14 {15     for(int i=0;i<4;i++)16         for(int j=0;j<4;j++)17             Mata.map[i][j]=0;18     Mata.map[0][0]=1,Mata.map[0][1]=(4*x*x)%m;19     Mata.map[0][2]=(m-4*x%m)%m,Mata.map[0][3]=1;20 21     Mata.map[1][1]=4*x*x%m,Mata.map[1][2]=(m-4*x%m)%m;//处理负数22     Mata.map[1][3]=1;23 24     Mata.map[2][1]=2*x%m,Mata.map[2][2]=m-1;//处理负数25 26     Mata.map[3][1]=1;27 }28 29 Matrix Mul(const Matrix &a,const Matrix &b)30 {31     Matrix c;32     for(int i=0;i<4;i++){33         for(int j=0;j<4;j++){34             c.map[i][j]=0;35             for(int k=0;k<4;k++){36                 c.map[i][j]+=a.map[i][k]*b.map[k][j];37                 if(c.map[i][j]>=m)c.map[i][j]%=m;38             }39         }40     }41     return c;42 }43 44 Matrix Pow(Matrix q,ll n)45 {46     Matrix p;47     for(int i=0;i<4;i++)48         for(int j=0;j<4;j++)49             p.map[i][j]=(i==j)?1:0;50     while(n){51         if(n&1){52             p=Mul(p,q);53         }54         n>>=1;55         q=Mul(q,q);56     }57     return p;58 }59 60 int main()61 {62   //  freopen("1.txt","r",stdin);63     int _case;64     scanf("%d",&_case);65     while(_case--){66         scanf("%I64d%I64d%I64d",&x,&n,&m);67         if(n==2){68             sum=(1*1+x*x)%m;69             printf("%I64d\n",sum);70         }else {71             Initiate(x);72             Matb=Pow(Mata,n-2);73  //           cout<<Matb.map[0][0]<<"**"<<Matb.map[0][1]<<"**"<<Matb.map[0][2]<<"***"<<Matb.map[0][3]<<endl;74             sum=((((1+x*x)%m)*Matb.map[0][0])%m+((x*x%m)*Matb.map[0][1]%m)+(x*Matb.map[0][2])%m+Matb.map[0][3])%m;75             printf("%I64d\n",sum);76         }77     }78     return 0;79 }
View Code

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3519

思路:令a(n)代表合法的个数,b(n)代表末两位不同,C(n)代表末两位相同。于是我们有如下递推关系式:

a(n)=2*a(n-1)+C(n-1);

b(n)=b(n-1)+C(n-1);

C(n)=b(n-1);

从而根据上式得出矩阵:

[2,0,1]   [a(n-1)]      [a(n)]

[0,1,1]   [b(n-1)]  =  [b(n)]

[0,1,0]   [C(n-1)]     [C(n)]

从而矩阵快速幂求出a(n).

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MOD 10007 7  8 struct Matrix{ 9     int map[3][3];10 }Mata,Matb;11 12 Matrix Mul(const Matrix &a,const Matrix &b)13 {14     Matrix c;15     for(int i=0;i<3;i++){16         for(int j=0;j<3;j++){17             c.map[i][j]=0;18             for(int k=0;k<3;k++){19                 c.map[i][j]+=(a.map[i][k]*b.map[k][j]);20                 c.map[i][j]%=MOD;21             }22         }23     }24     return c;25 }26 27 Matrix Pow(Matrix q,int n)28 {29     Matrix p;30     for(int i=0;i<3;i++)31         for(int j=0;j<3;j++)32             p.map[i][j]=(i==j)?1:0;33     while(n){34         if(n&1){35             p=Mul(p,q);36         }37         n>>=1;38         q=Mul(q,q);39     }40     return p;41 }42 43 int main()44 {45     Mata.map[0][0]=2,Mata.map[0][2]=1;46     Mata.map[1][1]=Mata.map[1][2]=1;47     Mata.map[2][1]=1;48     int n;49     while(~scanf("%d",&n)){50         if(n<=2)puts("0");51         else {52             Matb=Pow(Mata,n-2);53             printf("%d\n",2*(Matb.map[0][1]+Matb.map[0][2])%MOD);54         }55     }56     return 0;57 }
View Code

 

 

0 0