1 条题解
-
0
宝宝容斥。
记 表示从 走到 中途不经过 且恰好走 步的答案。发现直接处理只能限定 中一端不经过,故我们需要容斥。我们钦定路径 一端始终没有重复经过,容斥去 的重复经过。此时总方案数为从 走 步到 但中途不重复经过 的方案数,记之为 。对于重复经过 但不重复经过 的非法路径,划分其为两阶段,枚举第一次经过 走了 步,首先从 走 步到 且都不经过 ,再从 走 步回到 ,但是不经过 ,其中 。发现一阶段的方案数就是 ,记 表示从 走 步回到 但不经过 的方案数,那么二阶段方案数为 。于是我们有:
$$\text{Ans}_{s,t,k}=f_{s,t,k}-\sum_{d=1}^{k-1}\text{Ans}_{s,t,d}\times g_{t,s,k-d}.$$是好处理的,枚举起点 ,初始 ,枚举步数 ,转移 trivial:,要求存在边 且 。
考虑如何处理 。再次容斥。用 走 步回到 的总方案数减去其中经过了 的非法方案数。记 表示 走 步到 无任何限制的方案数,总方案数即 。对于非法路径,我们类似地划分其为两阶段,枚举最后一次经过 走了 步,首先从 走 步到 无其他限制,再从 走 步回到 但中途不重复回到 。前者即 ,后者即 。于是我们有:
$$g_{s,t,k}=h_{s,s,k}-\sum_{d=1}^{k-1} h_{s,t,d}\times f_{t,s,k-d}.$$类似 ,处理 naive。初始 ,枚举步数 ,转移 ,只要求 有边。
得到 后处理 。最后 输出答案。处理 复杂度 ,处理 复杂度 。
#include <bits/stdc++.h> #define LL long long #define ull unsigned long long #define uint unsigned int using namespace std; const int N = 110; const int M = 55; int n, Q, m; ull P; bool e[N][N]; ull F[M][N][N], H[M][N][N], Ans[M][N][N], G[M][N][N]; int main() { freopen(".in", "r", stdin); freopen(".out", "w", stdout); ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> m >> P; for (int i = 1, u, v; i <= m; i ++) cin >> u >> v, e[u][v] = 1; for (int s = 1; s <= n; s ++) { F[0][s][s] = H[0][s][s] = 1; for (int k = 1; k <= 50; k ++) for (int t = 1; t <= n; t ++) for (int v = 1; v <= n; v ++) if (e[t][v]) (H[k][s][v] += H[k - 1][s][t]) %= P; for (int k = 1; k <= 50; k ++) for (int t = 1; t <= n; t ++) for (int v = 1; v <= n; v ++) if (e[t][v] && v != s) (F[k][s][v] += F[k - 1][s][t]) %= P; } for (int s = 1; s <= n; s ++) for (int t = 1; t <= n; t ++) if (s != t) { for (int k = 1; k <= 50; k ++) { for (int d = 1; d < k; d ++) G[k][s][t] = (G[k][s][t] + H[d][s][t] * F[k - d][t][s] % P) % P; G[k][s][t] = (H[k][s][s] + P - G[k][s][t]) % P; } } for (int s = 1; s <= n; s ++) for (int t = 1; t <= n; t ++) if (s != t) { for (int k = 1; k <= 50; k ++) { for (int d = 1; d < k; d ++) Ans[k][s][t] = (Ans[k][s][t] + Ans[d][s][t] * G[k - d][t][s] % P) % P; Ans[k][s][t] = (F[k][s][t] + P - Ans[k][s][t]) % P; } } cin >> Q; int x, y, k; while (Q --) { cin >> x >> y >> k; cout << Ans[k][x][y] << "\n"; } return 0; }
- 1
信息
- ID
- 5765
- 时间
- 10000ms
- 内存
- 356MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者