1898: [Zjoi2005]Swamp 沼泽鳄鱼
矩阵乘法。
邻接矩阵用矩阵乘法可以得到最后的方案数
食人鱼是周期性的移动可以用12个矩阵表示。12个矩阵乘在一起得到第13个矩阵。
然后k/12的部分用第13个矩阵快速幂转移,再乘下剩余的矩阵。
#include<cstdio> #include<algorithm> #include<cstring> #define LL long long using namespace std; const int maxn = 50 + 10; const int mod = 10000; int n,m,p1,p2,k,nf; int t[maxn],q[maxn][maxn]; struct Matrix { int a[maxn][maxn]; int* operator [] (int x) { return a[x]; } Matrix operator * (Matrix b) { Matrix res; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) res[i][k]=(res[i][k]+a[i][j]*b[j][k])%mod; return res; } Matrix operator ^ (int e) { Matrix res,tmp=*this; res.init(); while(e) { if(e&1) res=res*tmp; tmp=tmp*tmp; e>>=1; } return res; } void init() { memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) a[i][i]=1; } Matrix() { memset(a,0,sizeof(a)); } }a[15],b,f; void build() { scanf("%d%d%d%d%d",&n,&m,&p1,&p2,&k); p1++; p2++; for(int i=1,u,v;i<=m;i++) { scanf("%d%d",&u,&v); u++; v++; b[u][v]=b[v][u]=1; } scanf("%d",&nf); for(int i=1;i<=nf;i++) { scanf("%d",&t[i]); for(int j=0;j<t[i];j++) { scanf("%d",&q[i][j]); q[i][j]++; } } for(int i=1;i<=12;i++) { a[i]=b; for(int j=1,v;j<=nf;j++) { v=q[j][i%t[j]]; for(int k=1;k<=n;k++) a[i][k][v]=0; } } b.init(); for(int i=1;i<=12;i++) b=b*a[i]; f.init(); f=f*(b^(k/12)); for(int i=1;i<=(k%12);i++) f=f*a[i]; printf("%d\n",f[p1][p2]); } int main() { build(); return 0; }