今天继续攻集训队论文的我
题意
一张无向图,不超过
50
50
个点
起点
s
s
终点
一个单位时间移动一次
一些食人鱼作周期运动 长度不超过
4
4
人不能碰到食人鱼
时刻 到达终点
u<=2∗109
u
<=
2
∗
10
9
分析
引理
我们观察数据发现
n
n
十分的小,那么就可以直接用邻接矩阵
而且有一种矩阵叫矩阵乘法
对于一张(无向)图:
那么我们想一想 G2 G 2 表示的意义是什么:
那么是不是就是表示 走2布的时候a−>b的方案数 走 2 布 的 时 候 a − > b 的 方 案 数 ,那么以此类推
走 k k 布的方案数就是了!
此题分析
我们用
Ak
A
k
表示走
k
k
布的情况下的方案数
而表示在走第
i
i
布是的图的情况(0,1)表示
那么如果没有食人鱼的话就是:
那么如果有食人鱼的话就是
那么我们看见食人鱼的循环是 2,3,4 2 , 3 , 4 不等,但是 lcm(2,3,4)=12 l c m ( 2 , 3 , 4 ) = 12
也就是意味着 G1=G13 G 1 = G 13 这两张图是一样的
那么我们可以 O(n3) O ( n 3 ) 预处理出add矩阵
那么答案的矩阵就是:
复杂度 O(n3log2q) O ( n 3 l o g 2 q )
代码:
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 55
#define M 25
#define R register
using namespace std;
int n, m, s, t, K, x, y, Nfish, Pow_time, leftn, ff[N], att[N][10];
struct matrix
{
int a[N][N];
matrix()
{
memset(a, 0, sizeof a);
}
} G[20], fuu, ans, fff;
inline matrix operator * (matrix x, matrix y)
{
matrix z;
for(R int i = 0; i < n; ++i)
for(R int j = 0; j < n; ++j)
for(R int k = 0; k < n; ++k)
{
z.a[i][j] += x.a[i][k] * y.a[k][j];
if(z.a[i][j] > 10000) z.a[i][j] %= 10000;
}
return z;
}
inline matrix Pow(matrix now, int y)
{
matrix res;
for(R int i = 0; i < n; ++i) res.a[i][i] = 1;
while(y)
{
if(y & 1) res = res * now;
now = now * now;
y >>= 1;
}
return res;
}
inline void init()
{
for(R int i = 1; i <= 12; i++)
{
G[i] = fuu;
for(R int j = 1; j <= Nfish; j++)
{
int to = att[j][((i + 1) % ff[j]) ? ((i + 1) % ff[j]) : ff[j]];
for(R int k = 0; k < n; k++)
G[i].a[k][to] = 0;
}
}
}
inline matrix solve()
{
Pow_time = K / 12;
leftn = K % 12;
matrix ans, fff;
for(R int i = 0; i < n; ++i) ans.a[i][i] = fff.a[i][i] = 1;
for(R int i = 1; i <= 12; ++i) fff = fff * G[i];
ans = ans * Pow(fff, Pow_time);
for(R int i = 1; i <= leftn; ++i)
{
ans = ans * G[i];
}
return ans;
}
inline int read()
{
int x=0;
char c=getchar();
bool flag=0;
while(c<'0'||c>'9'){if(c=='-')flag=1; c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return flag?-x:x;
}
int main()
{
n = read(), m = read(), s = read(), t = read(), K = read();
for(R int i = 1; i <= m; ++i)
{
x = read(), y = read();
fuu.a[x][y] = fuu.a[y][x] = 1;
}
Nfish = read();
for(R int i = 1; i <= Nfish; ++i)
{
ff[i] = read();
for(int j = 1; j <= ff[i]; ++j)
att[i][j] = read();
}
init();
ans = solve();
printf("%d\n", ans.a[s][t]);
return 0;
}