HDU_Steps8.3 矩阵应用 HDU1575 HDU1757 HDU2294 HDU2254 HDU2276 HDU2855 HDU3519 HDU3509
来源:互联网 发布:淘宝大码女装微胖 编辑:程序博客网 时间:2024/06/06 00:40
STEPS8.3一些矩阵的应用,还是比较难的
HDU1575 Tr A
矩阵相乘基础题
HDU1757 A Simple Math Problem
7.2中的题目,重复了,构造矩阵
HDU2294 Pendant
f[i][j]代表j种颜色组成i个珠子,有方程f[i][j]=f[i-1][j]*j+f[i-1][j-1]*(k-j-1),但由于N较大采用一般的方法DP必然按会超时的。考虑构造矩阵f[i]=A*f[i-1],然后允许的长度是k~n,所以ans=(A^k+....+A^n)*f[0],初始只有f[0][0]=1,其它都是0.所以答案是矩阵种的a[k][0]
#include<cstdio>#include<string.h>using namespace std;int cas,n,k;const int MOD=1234567891;typedef long long LL;struct mat{int a[31][31];mat(int type){memset(a,0,sizeof a);if(type==1){for(int i=0;i<=k;i++){a[i][i]=i;if(i>0)a[i][i-1]=k-i+1;}}}mat mult(mat b){//矩阵加法mat c(0);for(int i=0;i<=k;i++)for(int j=0;j<=k;j++)for(int l=0;l<=k;l++)c.a[i][j]=((LL)c.a[i][j]+(LL)a[i][l]*(LL)b.a[l][j])%MOD;return c;}mat add(mat b){//矩阵乘法mat c(0);for(int i=0;i<=k;i++)for(int j=0;j<=k;j++)c.a[i][j]=((LL)a[i][j]+(LL)b.a[i][j])%MOD;return c;}};//二分计算A^kmat binMat(int k){if(k<=1)return mat(k);mat m=binMat(k/2);m=m.mult(m);if(k&1)m=m.mult(mat(1));return m;}//二分计算A^l+...A^rmat cal(int l,int r){if(l==r)return binMat(l);int m=(l+r+1)/2;mat t=cal(l,m-1);//算前一半的和mat t2=binMat(m-l);//中介的矩阵t=t.add(t2.mult(t));if((r-l+1)&1)t=t.add(binMat(r));//如果是奇数,则加上最后一个return t;}int main(){scanf("%d",&cas);while(cas--){scanf("%d%d",&n,&k);printf("%d\n",cal(k,n).a[k][0]);}return 0;}
HDU2254 奥运
路径条数,只要把邻接矩阵乘起来就可以了。数据比较小,先打表,再再表中直接取就行了
#include<cstdio>#include<map>#include<string.h>using namespace std;int cas,n,v1,v2,t1,t2,ta,tb,ncity;int m[32][32];//标记初始矩阵map<int,int> mmap;struct jz{int a[32][32];jz(){}jz(int type){if(type==0)memset(a,0,sizeof a);if(type==1){for(int i=1;i<=ncity;i++)for(int j=1;j<=ncity;j++)a[i][j]=m[i][j];}}jz mult(jz jb){jz jc(0);for(int i=1;i<=ncity;i++){for(int j=1;j<=ncity;j++){for(int k=1;k<=ncity;k++){jc.a[i][j]=(jc.a[i][j]+a[i][k]*jb.a[k][j])%2008;}}}return jc;}}M[10001];int main(){while(scanf("%d",&n)!=EOF){mmap.clear();memset(m,0,sizeof m);ncity=1;for(int i=1;i<=n;i++){scanf("%d%d",&ta,&tb);if(mmap.count(ta)==0)mmap[ta]=ncity++;if(mmap.count(tb)==0)mmap[tb]=ncity++;m[mmap[ta]][mmap[tb]]++;}memcpy(M[0].a,m,sizeof m);for(int i=1;i<=10000;i++)M[i]=M[i-1].mult(jz(1));scanf("%d",&n);while(n--){int ans=0;scanf("%d%d%d%d",&v1,&v2,&t1,&t2);if(mmap.count(v1)==0||mmap.count(v2)==0){ans=0;}else{for(int i=t1-1;i<t2;i++){ans=(ans+M[i].a[mmap[v1]][mmap[v2]])%2008;}}printf("%d\n",ans);}}return 0;}
HDU2276 Kiki & Little Kiki 2
构造矩阵,第i个灯的状态d[i],以及它左边的灯的状态d[i-1],则下一秒d[i]=(d[i]+d[i-1])/2,一共就4种情况01,10,00,10,模拟一下就可以验证方程的正确性了,然后利用矩阵可以再logN内得到第N秒的状态,注意这里不能用递归二分矩阵,会暴栈
#include<cstdio>#include<string.h>using namespace std;int n,m;char s[105];struct jz{int a[101][101];jz(int type){memset(a,0,sizeof a);if(type==1){for(int i=1;i<=n;i++){a[i][i==1?n:i-1]=a[i][i]=1;}}if(type==2){//单位矩阵for(int i=1;i<=n;i++)a[i][i]=1;}}jz mult(jz b){jz c(0);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){for(int k=1;k<=n;k++){c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]);}c.a[i][j]%=2;//模操作是很占时间的!!}}return c;}};void outres(jz jj){int rs[105];memset(rs,0,sizeof rs);for(int i=1;i<=n;i++){for(int k=1;k<=n;k++){rs[i]=rs[i]+jj.a[i][k]*(s[k-1]-'0');}rs[i]%=2;}for(int i=1;i<=n;i++)printf("%d",rs[i]);printf("\n");}//二分矩阵的非递归写法jz binMat(int k){jz tmp(2),m(1); while(k){if(k&1)tmp=tmp.mult(m);m=m.mult(m);k=k>>1;}return tmp;}int main(){while(scanf("%d",&m)!=EOF){scanf("%s",s);n=strlen(s);jz r=binMat(m);outres(r);}return 0;}
HDU2855 Fibonacci Check-up
求sigma(c(n,k)*F(k)),其中F是Fibo数列,很容易想到用牛顿二项式展开,Fibo数列可以表示乘A^k*[f0,f1]
#include<cstdio>#include<string.h>using namespace std;int cas,n,m;/*(|1 0| + |0 1|)^n * |0 1| |1 1| * */struct jz{int a[3][3];jz(int type){memset(a,0,sizeof a);if(type==1){a[1][1]=a[2][1]=a[1][2]=1;a[2][2]=2;}}jz mult(jz b){jz c(0);c.a[1][1]=(a[1][1]*b.a[1][1]+a[1][2]*b.a[2][1])%m;c.a[1][2]=(a[1][1]*b.a[1][2]+a[1][2]*b.a[2][2])%m;c.a[2][1]=(a[2][1]*b.a[1][1]+a[2][2]*b.a[2][1])%m;c.a[2][2]=(a[2][1]*b.a[1][2]+a[2][2]*b.a[2][2])%m;return c;}};jz binmat(int k){if(k<=1)return jz(k);jz r=binmat(k/2);r=r.mult(r);if(k&1)r=r.mult(jz(1));return r;}int main(){scanf("%d",&cas);while(cas--){scanf("%d%d",&n,&m);if(n<=1)printf("%d\n",n);else{jz r=binmat(n);printf("%d\n",r.a[1][2]);}}return 0;}
HDU3519 Lucky Coins Sequence
一串硬币,至少有三个连续面相同的硬币的摆法有多少种,具体的解见注释
#include<cstdio>#include<string.h>using namespace std;/* d[i]代表合法的个数 * f[i][2]代表末两位相同 * f[i][1]代表末两位不同 * d[i]=2*d[i-1]+f[i-1][2] 合法的加上 正反 都依然合法,或者末两位相同再加上一个相同的也会合法 * f[i][2]=f[i-1][1] 末两位不同加上与末位相同的可以使其末两位相同 * f[i][1]=f[i-1][2]+f[i-1][1] 末两位相同或者不同 加上一个与末位不同的 都可以使其成为末两位不同的 * 构造矩阵求解 * | 2 1 0 | |d[i-1] | |d[i] | * | 0 0 1 | * |f[i-1][2]|=|f[i][2]| * | 0 1 1 | |f[i-1][1]| |f[i][1]| */struct mat{int a[4][4];mat(int type){memset(a,0,sizeof a);if(type==1){a[1][1]=2;a[1][2]=a[2][3]=a[3][2]=a[3][3]=1;}}mat mult(mat m){mat r(0);for(int i=1;i<=3;i++){for(int j=1;j<=3;j++){for(int k=1;k<=3;k++){r.a[i][j]=(r.a[i][j]+a[i][k]*m.a[k][j])%10007;}}}return r;}};mat binMat(int k){if(k<=1)return mat(k);mat m=binMat(k/2);m=m.mult(m);if(k&1)m=m.mult(mat(1));return m;}int main(){int n;while(scanf("%d",&n)!=EOF){if(n<=2){printf("0\n");continue;}mat r=binMat(n-2);printf("%d\n",(2*r.a[1][2]+2*r.a[1][3])%10007);}return 0;}
HDU3509 Buge's Fibonacci Number Problem
给出 F1=f1,F2=f2,Fn=aFn-1+bFn-2
求sigma(Fi^k)..i=1~n (n<1e10,k<50)
很麻烦的一道题目,思想还是用牛顿二项式构造矩阵求解
#include<cstdio>#include<string.h>using namespace std;typedef long long LL;int cas,f1,f2,a,b,n,m,k;int c[55][55],mpa[55],mpb[55],mpf1[55],mpf2[55];int s1,s2;/*这题要注意模的问题,一不小心就会越界 *展开二项式,构造矩阵 * 比如当k=3时,a=b=1时,矩阵如下 * | 0 0 0 1 0 | | f1^k | | f2^k | * | 0 0 1 1 0 | | f2*f1^(k-1)| | f3*f2^(k-1)| * | 0 1 2 1 0 |×| .. |=| .. | * | 1 3 3 1 0 | | f2^k | | f3^k | * | 1 3 3 1 1 | | s2 | | s3 | */ void init(){//初始化系数数组,二项式,以及a^n,b^n,以及前两相和//系数c[1][1]=1;c[2][1]=c[2][2]=1;for(int i=3;i<=54;i++){c[i][1]=c[i][i]=1;for(int j=2;j<=i-1;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%m;}//a,b的幂mpa[0]=mpb[0]=1;for(int i=1;i<=54;i++){mpa[i]=((LL)mpa[i-1]*(LL)a)%m;mpb[i]=((LL)mpb[i-1]*(LL)b)%m;}//f1,f2的幂mpf1[0]=mpf2[0]=1;for(int i=1;i<=54;i++){mpf1[i]=((LL)mpf1[i-1]*(LL)f1)%m;mpf2[i]=((LL)mpf2[i-1]*(LL)f2)%m;}//前两项s1=mpf1[k];s2=(mpf2[k]+mpf1[k])%m;}struct mat{int a[55][55];mat(int type){memset(a,0,sizeof a);if(type==1){a[k+1][k+1]=1;for(int i=0;i<=k+1;i++)for(int j=k,jj=0;j>=k-i;j--,jj++)if(i!=k+1)a[i][j]=(((LL)c[i+1][jj+1]*(LL)mpa[i-jj])%m*(LL)mpb[jj])%m;else a[i][j]=a[i-1][j];}}mat mult(mat b){mat c(0);for(int i=0;i<=k+1;i++)for(int j=0;j<=k+1;j++)for(int l=0;l<=k+1;l++)c.a[i][j]=(c.a[i][j]+((LL)a[i][l]*(LL)b.a[l][j])%m)%m;return c;}int sn(){int res=0;for(int i=0;i<=k;i++){res=(res+(((LL)a[k+1][i]*(LL)mpf1[k-i])%m*(LL)mpf2[i])%m)%m;}res=(res+((LL)a[k+1][k+1]*(LL)s2)%m)%m;return res;}};mat binMat(int x){if(x<=1)return mat(x);mat r=binMat(x/2);r=r.mult(r);if(x&1)r=r.mult(mat(1));return r;}int main(){scanf("%d",&cas);while(cas--){scanf("%d%d%d%d%d%d%d",&f1,&f2,&a,&b,&k,&n,&m);init();if(n==1)printf("%d\n",s1);else if(n==2)printf("%d\n",s2);else{mat r=binMat(n-2);printf("%d\n",r.sn());}}}
- HDU_Steps8.3 矩阵应用 HDU1575 HDU1757 HDU2294 HDU2254 HDU2276 HDU2855 HDU3519 HDU3509
- HDU2294 Pendant 矩阵应用
- HDU2254 奥运 矩阵应用
- HDU2855 Fibonacci Check-up 矩阵的应用
- hdu2254 矩阵
- HDU1575 Tr A 矩阵应用
- HDU2276 Kiki & Little Kiki 2 矩阵应用
- HDU3509(构造矩阵)
- HDU3519 【矩阵快速幂】
- HDU1757 A Simple Math Problem 矩阵应用
- hdu2294---Pendant (矩阵)
- hdu2254之矩阵乘法
- 快速矩阵幂HDU2254
- hdu2276 矩阵构造
- 快速矩阵幂HDU2276
- hdu2276(构建矩阵)
- 【HDU2294】Pendant-DP矩阵优化
- 矩阵乘法的应用(hdu1575,hdu1588,poj3070,poj3233,poj3613)
- 关于通用编程和Linux内核的链接
- 奋斗目标
- adroid风格和主题
- SmartUpload 上传文件
- js、jquery实用小技巧集合
- HDU_Steps8.3 矩阵应用 HDU1575 HDU1757 HDU2294 HDU2254 HDU2276 HDU2855 HDU3519 HDU3509
- ubuntu 安装smb共享文件夹
- 一个复习数据结构比较好的网站
- 我对DX11的理解和简化框架与快速游戏制作(续2)
- KDE 桌面环境下自定义快捷键
- 用异或来交换两个变量效率分析
- 不用中间变量交换两个double类型
- swappiness设置实际内存和swap的使用比率 /ubuntu优化
- ASP解决方案-Microsoft JET Database Engine(0x80004005)未指定错误