鱼的运动最多以12为周期。为了方便,就直接以12作为周期。
(令石墩标号为1~n)
f[i][j]
表示时刻
i
到
f[i][j]=∑nk=1f[i−1][k]
(时刻
i
,
K又很大。
那么就可以矩阵乘法优化,12个位一个周期,就将十二个
剩下的K%12个矩阵,再依次乘就好了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 10005
#define mod 10000
using namespace std;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,St,Ed,K,Num;
bool Link[55][55],Flag[13][55];
class matrix{
public:
int x,y;
int v[55][55];
}a,b[13],c,ans;
matrix Matrix_Mul(matrix aa,matrix bb)
{
matrix rtn;
rtn.x=aa.x,rtn.y=bb.y;
for(int i=1;i<=aa.x;i++)
for(int j=1;j<=aa.y;j++)
{
rtn.v[i][j]=0;
for(int k=1;k<=bb.y;k++)
rtn.v[i][j]=(rtn.v[i][j]+aa.v[i][k]*bb.v[k][j])%mod;
}
return rtn;
}
void Input_Init()
{
n=read(),m=read(),St=read()+1,Ed=read()+1,K=read();
for(int i=1;i<=m;i++)
{
static int x,y;
x=read(),y=read();x++,y++;
Link[x][y]=Link[y][x]=1;
}
for(int i=1;i<=12;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<j;k++) if(Link[j][k]) b[i].v[j][k]=b[i].v[k][j]=1;
Num=read();
while(Num--)
{
static int t,x;t=read();
for(int i=0;i<t;i++)
{
x=read()+1;
for(int j=i;j<=12;j+=t) Flag[j][x]=1;
}
}
for(int i=1;i<=12;i++)
{
for(int j=1;j<=n;j++) if(Flag[i][j])
for(int k=1;k<=n;k++) b[i].v[k][j]=0;
}
}
void Matrix_Pow(int y)
{
while(y)
{
if(y&1) a=Matrix_Mul(a,c);
c=Matrix_Mul(c,c);y>>=1;
}
}
void Solve()
{
for(int i=1;i<=n;i++) c.v[i][i]=a.v[i][i]=1;c.x=n,c.y=a.x=a.y=n;
for(int i=1;i<=12;i++) b[i].x=b[i].y=n,c=Matrix_Mul(c,b[i]);
int tmp=K/12;
Matrix_Pow(tmp);
tmp=K%12;
for(int i=1;i<=tmp;i++)
a=Matrix_Mul(a,b[i]);
ans.v[1][St]=1;ans.x=1,ans.y=n;
ans=Matrix_Mul(ans,a);
printf("%d\n",ans.v[1][Ed]);
}
int main()
{
Input_Init();
Solve();
return 0;
}