bzoj1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂相关的知识,希望对你有一定的参考价值。
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1898
求到达方案数...还是矩阵快速幂;
能够到达就把邻接矩阵那里赋成1,有鳄鱼的地方从各处来的路径都是0;
因为时间周期只有2,3,4,所以每12个时间就是一个循环;
可以用矩阵快速幂做了。
一开始写了个一团糟,也不明白样例为什么输出0了...
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int const mod=10000; int n,m,st,ed,K,head[55],ct,nf,ey[25][5],te[25],ans[55],tmp[55]; struct E{ int to,next; E(int t=0,int n=0):to(t),next(n) {} }edge[2505]; struct Matrix{ int a[55][55]; Matrix operator * (const Matrix &y) const { Matrix x; memset(x.a,0,sizeof x.a); for(int i=1;i<=n;i++) for(int k=1;k<=n;k++) for(int j=1;j<=n;j++) (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod; return x; } }s[15],b; void add(int x,int y){edge[++ct]=E(y,head[x]); head[x]=ct;} void build1() { for(int x=1;x<=n;x++) for(int i=1;i<=12;i++) for(int j=head[x],u;j;j=edge[j].next) s[i].a[x][u=edge[j].to]=1;// } void build2() { for(int i=1;i<=nf;i++) for(int t=1;t<=12;t++) for(int j=1;j<=n;j++) { int x=ey[i][t%te[i]]; // for(int k=head[x],y;k;k=edge[k].next) // s[j].a[y=edge[k].to][x]=0; s[t].a[j][x]=0; } } //void init(Matrix &x) //{ // memset(x.a,0,sizeof x.a); // for(int i=1;i<=55;i++) // for(int j=55;j;j--) // x.a[i][j]=1; //} void mul2(int a[55],int b[55][55],int c[55]) { int tmp[55]; for(int j=0;j<n;j++) { tmp[j]=0; for(int k=0;k<n;k++) tmp[j]=(tmp[j]+a[k]*b[k][j])%mod; } for(int j=0;j<n;j++) c[j]=tmp[j]; } int main() { scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K); st++; ed++; for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); x++; y++; add(x,y); add(y,x); } scanf("%d",&nf); for(int i=1;i<=nf;i++) { scanf("%d",&te[i]); for(int j=1;j<=te[i];j++) scanf("%d",&ey[i][j]),ey[i][j]++; } build1(); build2(); // init(s[13]); for(int i=1;i<=n;i++) b.a[i][i]=s[13].a[i][i]=1; for(int i=1;i<=12;i++)s[13]=s[13]*s[i]; // Matrix b; init(b); int t=K/12; while(t) { if(t&1)b=b*s[13]; s[13]=s[13]*s[13]; t>>=1; } t=K%12; for(int i=1;i<=t;i++)b=b*s[i]; // for(int i=1;i<=55;i++) // for(int j=1;j<=55;j++) // if(b.a[i][j])printf("b:%d ",b.a[i][j]); // tmp[st]=1; // for(int i=1;i<=n;i++) // for(int j=1;j<=n;j++) // (ans[i]+=tmp[j]*b.a[j][i])%=mod; ans[st]=1; mul2(ans,b.a,ans); printf("%d",ans[ed]); return 0; }
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int const mod=10000; int n,m,st,ed,K,nf,ey[5]; struct Matrix{ int a[55][55]; Matrix operator * (const Matrix &y) const { Matrix x; memset(x.a,0,sizeof x.a); for(int i=1;i<=n;i++) for(int k=1;k<=n;k++) for(int j=1;j<=n;j++) (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod; return x; } Matrix(){memset(a,0,sizeof a);}// void init() { for(int i=1;i<=n;i++) a[i][i]=1; } }s[15],b; Matrix operator ^ (Matrix a,int k) { Matrix ret; ret.init(); while(k) { if(k&1)ret=ret*a; a=a*a; k>>=1; } return ret; } int main() { scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K); st++; ed++; for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); x++; y++; for(int j=1;j<=12;j++) s[j].a[x][y]=s[j].a[y][x]=1; } scanf("%d",&nf); for(int i=1,tt;i<=nf;i++) { scanf("%d",&tt); for(int j=1;j<=tt;j++) scanf("%d",&ey[j]),ey[j]++; for(int j=1;j<=12;j++) for(int k=1;k<=n;k++) s[j].a[k][ey[j%tt+1]]=0;//+1 } s[13].init(); for(int i=1;i<=12;i++)s[13]=s[13]*s[i]; b=s[13]^(K/12); for(int i=1;i<=K%12;i++)b=b*s[i]; printf("%d",b.a[st][ed]); return 0; }
以上是关于bzoj1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1898[Zjoi2005]Swamp 沼泽鳄鱼 矩阵乘法
bzoj1898: [Zjoi2005]Swamp 沼泽鳄鱼
bzoj 1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂