Fate
P11563 【MX-X7-T4】[LSOT-3] 命运
题意
给定一个长度为
对每个
1 \le i \le n ,都有a_i=p_i 或者a_{p_i}=i 成立。
分析
评价为比较综合和复杂的计数题,难度不止蓝,没有做出来。由于笔者做了很久,所以这篇题解会比较废话。
虽然题目描述很抽象,完全不懂在说什么,但是可以明显看出来一定的图论倾向 。
会被第
i 个事件影响的是第a_i 个事件经历了第
i 个事件后影响了事件p_i
我们将
记
对每个
1 \le i \le n ,都有a_i = p_i 或者a_{p_i} = i 成立 。
我们分析这个条件在
对于
也就是说
注意到
由于
而
并非如此,如果
所以
如图所示
我们考虑对
先考虑
然后是
记
容斥
但是还没完,我们还遗漏了一个点 。
在
在上述的计数过程中,如果这个长度为
这其实是本质相同的一种方案,我们应想办法排除 。
以下我们来仔细地处理链的部分的方案数 。
我们记
而链的部分的答案就是
通常而言,“恰好” 是不好计算的,而 “钦定” 是好计算的 。我们记
那么
但是 “钦定” 和 “恰好” 是差得远的,当我们钦定
我们可以推得它们之间的关系是
而如果我们不考虑二元环,也就是上文我们原先的算法,答案就是
容斥的一个很重要的功能就是建立“钦定”与“恰好”之间的联系 ,我们考虑使用容斥。
一般来讲我们可以用容斥计算 “满足任意条件” 或 “满足所有条件” 。但是这个东西显然不符合我们所熟知的经典容斥模型 ,我们仍然可以使用容斥计算它吗 ?
仍然可以
只不过我们不能无脑地套用
在分析容斥系数时,我们应该围绕着这些核心对象
-
我要算什么
-
我实际算了什么
-
我多算了什么
在这个问题中,我们要求所有的 “恰好
如果我们按照原先不考虑二元环的方法进行计数,即
我们发现对于每个恰好的方案
我们又希望
所以每个
列表如下
| 恰好 d 个二元环 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| 实际算了 | 2 | 4 | 8 | 16 | 32 |
| 期望 | 1 | 1 | 1 | 1 | 1 |
| 多算了 | 1 | 3 | 7 | 15 | 31 |
我们逐项考虑容斥系数
对于
对于
| 恰好 d 个二元环 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| g(0)贡献 | 2 | 4 | 8 | 16 |
| g(1)贡献 | -1 | -4 | -12 | -32 |
| 最终 | 1 | 0 | -4 | -16 |
然后我们发现
| 恰好 d 个二元环 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| g(0)贡献 | 2 | 4 | 8 | 16 |
| g(1)贡献 | -1 | -4 | -12 | -32 |
| g(2)贡献 | 0 | 1 | 6 | 24 |
| 最终 | 1 | 1 | 2 | 8 |
然后令
| 恰好 d 个二元环 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| g(0)贡献 | 2 | 4 | 8 | 16 |
| g(1)贡献 | -1 | -4 | -12 | -32 |
| g(2)贡献 | 0 | 1 | 6 | 24 |
| g(3)贡献 | 0 | 0 | -1 | -8 |
| 最终 | 1 | 1 | 1 | 0 |
然后令
| 恰好 d 个二元环 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| g(0)贡献 | 2 | 4 | 8 | 16 |
| g(1)贡献 | -1 | -4 | -12 | -32 |
| g(2)贡献 | 0 | 1 | 6 | 24 |
| g(3)贡献 | 0 | 0 | -1 | -8 |
| g(4)贡献 | 0 | 0 | 0 | 1 |
| 最终 | 1 | 1 | 1 | 1 |
我们递归地求下去,可以发现
最终得到
再乘上普通环部分的答案
不止容斥
不过除了容斥,我们还可以有其他办法。
有点类似于二项式反演的基本形式,但是多了一个很丑陋的
但是它依然可以通过一些处理,应用二项式反演 !
变形得到
令
则有
这样我们可以对
进行二项式反演
将
将
得到
经典的交换求和次序得到
我们发现内部求和就是经典的二项式展开
然后我们就得到了和上面一样的东西
总答案是
终于写完了...
代码
核心代码如下,完整代码请自行访问剪贴板 或 提交记录
mint fc[N], fcv[N], inv[N], pw2[N];
mint binom(int n, int m) { return fc[n] * fcv[n - m] * fcv[m]; }
struct E {
int u, v, vis;
int get(int x) { return u ^ v ^ x; }
} e[N];
int n, p[N];
ve(int) g[N];
bool vis[N];
int tim, cnt;
int ring, ring2, chain;
int deg[N];
void dfs(int u, int fa, int &tp) {
++cnt, vis[u] = 1;
for (int ei : g[u]) {
if (e[ei].vis) { continue; }
e[ei].vis = 1;
int v = e[ei].get(u);
if (v == fa) {
tp = 1;
deg[v]--, deg[u]--;
} else {
if (vis[v]) {
tp = 2;
} else {
dfs(v, u, tp);
}
}
}
}
void task() {
n = rd();
L(i, 1, n) {
int x = rd();
p[i] = x;
e[i] = {i, x, 0};
g[i].push_back(i), g[x].push_back(i);
}
L(i, 1, n) { deg[i] = siz(g[i]); }
L(i, 1, n) {
if (!vis[i]) {
++tim, cnt = 0;
int tp = 0;
dfs(i, 0, tp);
if (tp == 1) {
chain++, ring2 += (cnt == 2);
} else {
ring += (cnt > 1);
}
}
}
L(i, 1, n) {
if (deg[i] > 2) { return wr("0\n"), void(); }
}
mint ans(0);
L(i, 0, ring2) {
ans += mint(neg1(i & 1)) * binom(ring2, i) * fc[chain - i] *
pw2[chain - i];
}
ans *= pw2[ring];
wr("%lld\n", ans.v);
}
鸣谢
E.Space.
Flying_Without_Wings
本题第一篇题解