您的位置:首页 > 其它

【日更】矩阵方面的各种习题?

2017-11-06 20:30 375 查看
恩……大二小萌新。

老板说要开始系统的学算法了呢恩……。

我先把之前开的矩阵习题做完再说别的好了。

然后后面可能会有一些最近刚出的题……2017年的icpc什么的。

打算停止更新啦……需要用的dp啊递推啊什么的知识太多了,只凭着数学有点忙不过来,先去补点dp。

题目列表来自http://blog.csdn.net/a601025382s/article/details/10251613

1.hdu 1005 矩阵基础题

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10251423

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=2;
const int mod=7;

struct matrix{
int x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int a,b,n;
while(scanf("%d%d%d",&a,&b,&n)!=EOF){
if(a==0 && b==0 && n==0) break;
matrix st;
st.x[0][0]=a;
st.x[0][1]=1;
st.x[1][0]=b;
st.x[1][1]=0;
st=powmatrix(st,n-1);
printf("%d\n",(st.x[0][1]+st.x[1][1])%mod);
}
return 0;
}


2.hdu 1575 矩阵基础题

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10122331

#include<stdio.h>
#include<string.h>
using namespace std;

int m;
const int mod=9973;

struct matrix{
int x[10][10];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int T;
scanf("%d",&T);
while(T--){
matrix st;
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&st.x[i][j]);
m=n;
st=powmatrix(st,k);
int sum=0;
for(int i=0;i<n;i++)
sum+=st.x[i][i];
printf("%d\n",sum%mod);
}
return 0;
}


3.hdu 1757 矩阵基础题

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10122695

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=10;
int mod;

struct matrix{
int x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int n;
while(scanf("%d%d",&n,&mod)!=EOF){
matrix st;
for(int i=0;i<10;i++)
for(int j=0;j<10;j++) st.x[i][j]=0;
for(int i=0;i<=9;i++)
scanf("%d",&st.x[0][i]);
st.x[1][0]=st.x[2][1]=st.x[3][2]=st.x[4][3]=st.x[5][4]=st.x[6][5]=st.x[7][6]=st.x[8][7]=st.x[9][8]=1;
st=powmatrix(st,n-9);
printf("%d\n",(9*st.x[0][0]+8*st.x[0][1]+7*st.x[0][2]+6*st.x[0][3]+5*st.x[0][4]+4*st.x[0][5]+3*st.x[0][6]+2*st.x[0][7]+st.x[0][8])%mod);
}
return 0;
}


4.poj 3734 找出递推关系,然后用矩阵加速

题目链接:http://poj.org/problem?id=3734

题解代码:http://blog.csdn.net/a601025382s/article/details/10240251

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=3;
const int mod=10007;

struct matrix{
int x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
matrix st;
st.x[0][0]=2;
st.x[0][1]=1;
st.x[0][2]=0;
st.x[1][0]=2;
st.x[1][1]=2;
st.x[1][2]=2;
st.x[2][0]=0;
st.x[2][1]=1;
st.x[2][2]=2;
st=powmatrix(st,n);
printf("%d\n",st.x[0][0]%mod);
}
return 0;
}


5.poj 2888 较难题,需要用到置换(burnside引理),欧拉phi函数,最后用矩阵加速

题目链接:http://poj.org/problem?id=2888

题解代码:http://blog.csdn.net/a601025382s/article/details/10239295

6.poj 3420 dp+矩阵(相关的有poj2663,poj2411)

题目链接:http://poj.org/problem?id=3420

题解代码:http://blog.csdn.net/a601025382s/article/details/10218563

这可能是我做的第一道比较难……对不起,至少不是基础题的矩阵题,置于前面那道矩阵+Burnside引理+欧拉函数+不动点的例题……恩……等我什么时候脑子清楚了再说,刚开始练习矩阵的时候被板子坑的不行。

然后这道题其实就是一个递推,非要说dp的话其实也不用。

首先尝试用递推解法来解。我们首先用手模拟画出4*2,4*3,4*4,4*5以及4*6的不可分割的矩阵。令a
表4*n规模的矩阵的摆放骨牌总数,b
表示4*n规模的不可分割的矩阵个数。

我们会发现a[1]=b[1]=1,b[2]=4,并且当n>=3时有以下规律:

当n为奇数时:b
=2

当n为偶数时:b
=3

然后按照递推关系可得公式:a
=a[n-1]*b[1]+a[n-2]*b[2]+…a[1]*b[n-1]+a[0]*b

又因为b
=b[n-2]=b[n-4]=…

b[n-1]=b[n-3]=b[n-5]=…

所以上面推出的公式有把无限项消掉的可能。

由公式得:a[n-2]=a[n-3]*b[1]+a[n-4]*b[2]+…a[1]*b[n-3]+a[0]*b[n-2]

将两个式子相减可得a
-a[n-2]=b[1]*a[n-1]+b[2]*a[n-2]+(b[3]-b[1])*a[n-3]+(b[4]-b[2])*a[n-4]

然后我们把b[1],b[2],b[3],b[4]代进去。

得到递推公式:a
=a[n-1]+5a[n-2]+a[n-3]-a[n-4]

说是需要用轮廓线dp验证一下可是我就是因为不会轮廓线dp才用的递推嘛。

然后就是很正常的四阶矩阵了。

下面ac代码。

不得不说我在结果那边wa了很久因为结果有可能是负的需要加个mod再模mod。

然后改了又wa了因为1%1=0,我当时下意识1是直接输出的。

总之,很烦。

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=4;
int mod;

struct matrix{
int x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int n;
while(scanf("%d%d",&n,&mod)!=EOF){
if(n==0&&mod==0) break;
if(n==1)
printf("%d\n",1%mod);
else if(n==2)
printf("%d\n",5%mod);
else if(n==3)
printf("%d\n",11%mod);
else{
matrix st;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++) st.x[i][j]=0;
st.x[0][0]=1;
st.x[0][1]=5;
st.x[0][2]=1;
st.x[0][3]=-1;
st.x[1][0]=st.x[2][1]=st.x[3][2]=1;
st=powmatrix(st,n-3);
printf("%d\n",((11*st.x[0][0]+5*st.x[0][1]+st.x[0][2]+st.x[0][3])%mod+mod)%mod);
}
}
return 0;
}


7.zoj 3690 递推+矩阵

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3690

题解代码:http://blog.csdn.net/a601025382s/article/details/8742961

之前矩阵做了几道题思路被限制住了……因为每次都是推的单一数列的递增关系,然后碰到有关联的两组数列就不知道怎么弄了……我的锅。

然后题目的意思是有n个人,m个数和一个k,现在每个人可以选择一个数,但是要求如果相邻的两个人选择相同的数,那么这个数要大于k。

假设F(n)表示前n个人第n个人选择的数大于k的个数,G(n)表示的是前n个人第n个人选择的数小于等于k的个数,那么F(n) = F(n-1) x (m-k)+G(n-1) x (m-k) , G(n) = F(n-1) x k+G(n-1) x (k-1) , 最后的结果就是F(n)+G(n)。(里面的x就是乘……两个*会自动转化成斜体我也很无奈。)

前面递归写出来都是an,an-1用矩阵和an-1,an-2表示的对吧,然后这题是F(n),G(n)用矩阵和F(n-1),G(n-1)表示……额算是两个一维矩阵?其实也很好理解只是因为我菜所以想了很久……恩。

有的地方会超int要注意,wa了一发。

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=2;
const int mod=1000000007;

struct matrix{
long long x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int n,p,k;
while((scanf("%d%d%d",&n,&p,&k))!=EOF){
matrix st;
st.x[0][0]=p-k;
st.x[0][1]=p-k;
st.x[1][0]=k;
st.x[1][1]=k-1;
st=powmatrix(st,n-1);
printf("%d\n",(st.x[0][0]*(p-k)+st.x[0][1]*k+st.x[1][0]*(p-k)+st.x[1][1]*k)%mod);
}
return 0;
}


8.poj 3150 循环矩阵题,从前一组状态推出后一组状态即可,不过n太大,需要用循环矩阵加速

题目链接:http://poj.org/problem?id=3150

题解代码:http://blog.csdn.net/a601025382s/article/details/9840613,在uva交的,poj上输入输出格式可能不一样

9.hdu 4565 13年长沙邀请赛的题目,需要数论知识推出矩阵关系

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10045229

是的所以我又空了一道题,来我们先做简单点的。

啊这题,首先第一反应是快速幂,然后不行,有小数。接着考虑矩阵快速幂,我们的目的是把小数排除掉,我第一个想法是从展开式里做文章,把小数分成整数部分和小数部分,小数乘小数的舍掉因为永远小于1,后来推了推不是很好实现。

然后我想到直接把可能出现小数部分的始作俑者提出来,也就是√b。

自然而然的可以想到,Sn一定可以用一个整数和一个带系数的√b项表示,即Sn=Xn+Yn*√b。

Xn+Yn*√b = (Xn-1 + Yn-1*√b)*(a+√b)

Xn+Yn*√b = a*Xn-1 + a*Yn-1*√b + Xn-1*√b + b*Yn-1

把整数和带√b的项分别合并,显然得:

Xn = a*Xn-1 + b*Yn-1

Yn = Xn-1 + a*Yn-1

然后就跟第七题一样构建矩阵做就好啦……。

这道题其实我wa了很多次,我写矩阵都是很规矩按照公式来的,从x1开始推就乘n-1次,从x0开始推就乘n次这样的,最后也是很规矩的把系数一项一项乘进去。这题本来也是这样的,但是后面精度一直爆,其实我也不知道是不是爆了精度,只不过我比较自信其他的没写错。最后还是改成了n次相乘才过了题。

……可是我看了看取值范围还是不觉得会爆long long啊就很烦。

下面ac代码。

#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;

const int m=2;
int mod;

struct matrix{
long long x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,int b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
int a,b,n;
while((scanf("%d%d%d%d",&a,&b,&n,&mod))!=EOF){
matrix st;
st.x[0][0]=a;
st.x[0][1]=b;
st.x[1][0]=1;
st.x[1][1]=a;
st=powmatrix(st,n);
printf("%lld\n",2*st.x[0][0]%mod);
}
return 0;
}


10.hdu 4686 推公式,需要点时间

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10114885

这题一开始我以为我和上一题一样死大数了,后来发现死0的特判了,wa的不值。

这题就是推一个关于an,bn,fn,Sn的矩阵,其中fn=an*bn,Sn为所求前n项和。然后推出来你发现递推公式里有常数项,所以就需要创一个关于an,bn,fn,Sn,1的五维矩阵,最后的1用来抵常数项。

递推公式推出来挺简单的,写着太麻烦了我就不写了,看代码就行,代码是按照数学矩阵规范写的。

以下ac代码。

#include<stdio.h>
#include<string.h>
using namespace std;

const int m=5;
const int mod=1000000007;

struct matrix{
long long x[m][m];
};

matrix mutimatrix(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<m;k++){
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
temp.x[i][j]%=mod;
}
return temp;
}

matrix powmatrix(matrix a,long long b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<m;i++)
temp.x[i][i]=1;
while(b){
if(b%2==1) temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
b=b/2;
}
return temp;
}

int main(){
long long n;
while((scanf("%lld",&n))!=EOF){
long long a0,ax,ay,b0,bx,by;
scanf("%lld%lld%lld%lld%lld%lld",&a0,&ax,&ay,&b0,&bx,&by);
a0%=mod;
b0%=mod;
matrix st;
st.x[0][0]=ax%mod;
st.x[0][1]=0;
st.x[0][2]=0;
st.x[0][3]=0;
st.x[0][4]=ay%mod;
st.x[1][0]=0;
st.x[1][1]=bx%mod;
st.x[1][2]=0;
st.x[1][3]=0;
st.x[1][4]=by%mod;
st.x[2][0]=ax*by%mod;
st.x[2][1]=ay*bx%mod;
st.x[2][2]=ax*bx%mod;
st.x[2][3]=0;
st.x[2][4]=ay*by%mod;
st.x[3][0]=ax*by%mod;
st.x[3][1]=ay*bx%mod;
st.x[3][2]=ax*bx%mod;
st.x[3][3]=1;
st.x[3][4]=ay*by%mod;
st.x[4][0]=0;
st.x[4][1]=0;
st.x[4][2]=0;
st.x[4][3]=0;
st.x[4][4]=1;
st=powmatrix(st,n-1);
if(n==0) printf("0\n");
else printf("%lld\n",(st.x[3][0]*a0%mod+st.x[3][1]*b0%mod+st.x[3][2]*((a0*b0)%mod)%mod+a0*b0%mod+st.x[3][4]%mod)%mod);
}
return 0;
}


11.hdu 3893 状态很多,需要通过对称性来简化题目

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10122107

12.hdu 4291 找循环,在3次矩阵

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10133651

13.hdu 2256 跟长沙邀请赛的那题很想,将2n中的2花掉,就一样了

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10135719

14.hdu 2604 dp+矩阵,

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10137011

15.fzu 1683 又是函数求和s
=s[n-1]+f
,以此推矩阵

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10142725

16.hdu 1588 需要推导下,等比矩阵和。。

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10147389

17.hdu 3117 这题也用到斐波那契通项公式,不过不是用来推矩阵的

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10150441

18.hdu 2254 经典题,用矩阵求路径的走法方案数

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10159845

19.hdu 2276 普通矩阵题,直接求状态即可,虽然矩阵是个循环矩阵。。

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10160467

20.fzu 1692 又一道循环矩阵题

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10161947

21.zoj 2853 概率的矩阵题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2853

题解代码:http://blog.csdn.net/a601025382s/article/details/10170785

22.zoj 2974 还是概率矩阵题,不过需要注意下特殊的数据

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2974

题解代码链接:http://blog.csdn.net/a601025382s/article/details/10171941

23.poj 3735 理解各个处理方式有点。。推出来就简单了

题目链接:http://poj.org/problem?id=3735

题解代码:http://blog.csdn.net/a601025382s/article/details/10173521

24.hdu 2855 较难题,需要用斐波那契数列通项公式推导,当然你眼力够强,也可以从数据里得出规律

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10195939

25.hdu 2971 较难题,主要需要推公式,有点难发现

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10196907

26.hdu 2294 dp+矩阵,不多说了,只要会用长度和种数dp就好了

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

题解代码:http://blog.csdn.net/a601025382s/article/details/10198553

27.hdu 3233 等比矩阵和,可以讲矩阵看做一个元素,这样就可以得到以矩阵为元素的矩阵了

题目链接:http://poj.org/problem?id=3233

题解代码:http://blog.csdn.net/a601025382s/article/details/10199559

28.poj 3744 较难题,根据地雷前后的状态来推,需要多次矩阵

题目链接:http://poj.org/problem?id=3744

题解代码:http://blog.csdn.net/a601025382s/article/details/10209009
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息