[ZJOI2005]沼泽鳄鱼

Posted by Dispwnl on April 26, 2019

题目

题解

众所周知,因为鳄鱼名字里有鱼,食人鱼名字里有鱼,所以鳄鱼=食人鱼

发现不能经过的点最多有$12$种情况,即$lcm(2,3,4)$

所以把$12$种情况的矩阵都处理出来,然后$12$个时间一起处理,最后剩下的$k\%12$个时间暴力乘起来即可

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
using namespace std;
const int N=55,mod=10000;
struct Mx{
	int a[N][N];
	int* operator[] (int x) {return a[x];}
}a,emp,w[13];
int n,k,m,s,t,nfs;
int p[4];
Mx operator* (Mx a,Mx b)
{
	Mx c=emp;
	for(int i=0;i<n;++i)
	  for(int j=0;j<n;++j)
	    for(int k=0;k<n;++k)
	      {
	      	c[i][j]+=1ll*a[i][k]*b[k][j]%mod;
	      	if(c[i][j]>=mod) c[i][j]-=mod;
		  }
	return c;
}
int read()
{
	int x(0);
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
	return x;
}
Mx Pow(Mx a,int b)
{
	Mx ans=emp;
	for(int i=0;i<n;++i)
	  ans[i][i]=1;
	for(;b;b>>=1,a=a*a)
	  if(b&1) ans=ans*a;
	return ans;
}
int main()
{
	n=read(),m=read(),s=read(),t=read(),k=read();
	for(int i=1,x,y;i<=m;++i)
	  x=read(),y=read(),a[x][y]=a[y][x]=1;
	for(int i=1;i<=12;++i)
	  w[i]=a;
	nfs=read();
	for(int i=1,t;i<=nfs;++i)
	  {
	  	t=read();
	  	for(int j=0;j<t;++j)
	  	  p[j]=read();
	  	for(int j=1;j<=12;++j)
	  	  for(int k=0;k<n;++k)
	  	    w[j][k][p[j%t]]=0;
	  }
	a=emp;
	for(int i=0;i<n;++i)
	  a[i][i]=1;
	for(int i=1;i<=12;++i)
	  a=a*w[i];
	a=Pow(a,k/12);
	for(int i=1;i<=k%12;++i)
	  a=a*w[i];
	return printf("%d",a[s][t]),0;
}