矩阵小结
来源:互联网 发布: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).
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
题目链接: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)即可。
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
题目链接: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)了。
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
题目链接: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);
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
题目链接: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:这里由于有负数出现,取模的时候得小心。
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
题目链接: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).
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
- 矩阵小结
- 矩阵小结
- 矩阵小结
- 矩阵专题小结
- 图形变换矩阵小结
- 矩阵求导小结
- 矩阵快速幂小结
- 矩阵乘法小结
- 矩阵范数小结
- 矩阵乘+高斯消元专题小结【矩阵乘法】
- opengl的矩阵计算小结
- 矩阵快速幂锦上添花小结
- 矩阵的求导问题小结
- numpy矩阵属性知识小结
- numpy矩阵基础知识回顾小结
- 有序矩阵查找 -- 算法小结
- 矩阵乘+高斯消元专题小结【高斯消元】
- matlab 矩阵数据处理小结(1)
- hdu 4587(割点的应用)
- 二战时泰国军队入侵中国:替日本火中取栗
- hdu 4576(概率dp+滚动数组)
- hdu 4681(枚举+dp)
- hdu 4679(树形dp)
- 矩阵小结
- poj 3469(网络流模版)
- 无法启动调试 未安装silverlight developer 运行时 解决办法
- hdu 4705(树形DP)
- hdu 4704(费马小定理)
- poj 2125(最小割)
- poj 2135(最小费用最大流)
- poj 2391(二分+最大流)
- poj 2455(二分+最大流)