链接
题目描述
一个池塘,一些鳄鱼,鳄鱼有周期(
2
≤
周
期
≤
4
2\leq周期\leq4
2≤周期≤4)的运动路线,你要从某个点恰好走某个步数走到另一个点,然后你不能和任何一个鳄鱼同时存在于一个点上,问你有多少种走法。
方案数对 10000 取模。
样例输入
6 8 1 5 3
0 2
2 1
1 0
0 5
5 1
1 4
4 3
3 5
1
3 0 5 1
样例输出
2
思路
考虑怎么样去掉周期
周期有2,3,4,那就是长度为12的大周期
然后对于这个大周期,那就求出每个基础的矩阵,那对于每个时间,我们只需要把被鳄鱼占领的点去掉即可得到改动的矩阵
然后就先乘 k / 12 k / 12 k/12个大周期,然后再乘剩下的余数即可
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int mo = 10000;
struct matrix
{
int n, m;
int a[55][55];
}nor, ans, all, c, t[5005], E;
int n, m, s, e, k, num;
int P[5005][5005], T[5005];
matrix operator *(matrix a, matrix b)
{
c.n = a.n;
c.m = b.m;
for(int i = 0; i < c.n; ++i)
for(int j = 0; j < c.m; ++j)
c.a[i][j] = 0;
for(int k = 0; k < a.m; ++k)
for(int i = 0; i < c.n; ++i)
for(int j = 0; j < c.m; ++j)
c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]) % mo) % mo;
return c;
}
int main()
{
scanf("%d%d%d%d%d", &n, &m, &s, &e, &k);
for(int i = 1; i <= m; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
nor.a[x][y] = nor.a[y][x] = 1;
}
nor.n = n;
nor.m = n;
E.n = n;
E.m = n;
for (int i = 0; i < n; i++)
E.a[i][i] = 1;
all = E;
ans = E;
scanf("%d", &num);
for(int i = 1; i <= num; ++i)
{
scanf("%d", &T[i]);
for(int j = 0; j < T[i]; ++j)
scanf("%d", &P[i][j]);
}
for(int i = 1; i <= 12; ++i)
{
t[i] = nor;
for(int j = 1; j <= num; ++j)
{
int to = P[j][i % T[j]];
for(int k = 0; k < n; ++k)
t[i].a[k][to] = 0;//标记被占领的位置
}
all = all * t[i];
}//先乘出大周期矩阵
int allt = k / 12;
while(allt)
{
if(allt & 1) ans = ans * all;
all = all * all;
allt /= 2;
}
allt = k % 12;
for(int i = 1; i <= allt; ++i)
ans = ans * t[i];
printf("%d", ans.a[s][e]);
}