题解:P17316 [KismetOI 2026 I] 孤独绽放的彼岸花
考察选手是否做过 CF995F。
题目相当于给每个节点赋一个权值 \(a_u\),满足:
- \(a_u\in[0,X]\)。
- \(a_{fa_u}\leq a_u\)。
- 存在 \(dep_u=k\) 的点 \(u\),使得 \(a_u\leq S\)。
先判掉一些 corner。若树中不存在 \(dep_u=k\) 的点,则答案为 \(0\)。在此基础上,若 \(X\leq S\),则答案为 \(1\)。
接下来考虑 \(X>S\) 怎么做。
考虑先求总方案数。这个不就是我们 CF995F 吗?具体来说,令 \(f_{u,i}\) 表示考虑 \(sub_u\) 内的点,给每个节点赋一个 \([0,i]\) 内的权值,满足 \(a_{fa_v}\leq a_v\),此时的方案数。转移时枚举 \(a_u=j\):
那么答案就是 \(f_{1,X}-f_{1,X-1}\)。
构造多项式 \(F_u\) 使得 \(F_u(x)=f_{u,x}\)。对点值做前缀和会使多项式次数 \(+1\),而在叶子节点处有 \(F_u(x)=x+1\),因此容易归纳得出 \(\deg F_u=sz_u\)。
于是我们只需维护 \(F_u(0),\cdots,F_u(n-1)\) 这些点值。最后求答案时先对 \(F_1\) 的点值差分一下,再用 \(x\) 坐标连续的单点插值求出答案即可。时间复杂度为 \(\mathcal{O}(n^2)\)。
回到本题,容易考虑正难则反,要求对于每个 \(dep_u=k\) 的点,都有 \(a_u>S\)。对于 \(dep_u<k\) 的点 \(u\),定义 \(g_{u,i}\) 表示考虑 \(sub_u\) 内的点,给每个节点赋一个 \([0,X]\) 内的权值,满足:
- \(a_u=S-i\)。
- \(a_{fa_v}\leq a_v\)。
- 对于每个 \(dep_v=k\) 的点,都有 \(a_v>S\)。
此时的方案数。
注意这里 \(i\) 记录的是 \(S-a_u\),这是为了方便维护点值。
转移考虑分讨。若 \(a_v>S\),则 \(sub_v\) 内的 \(dep=k\) 的点自然满足第二个条件,贡献为 \(f_{v,X-S-1}\);若 \(a_v\leq S\),则贡献为 \(\sum_{j=0}^i g_{v,j}\)。由此得到转移:
构造多项式 \(G_u\) 使得 \(G_u(x)=g_{u,x}\)。和前面一样,容易归纳得出 \(\deg G_u<sz_u\),同样维护 \(G_u(0),\cdots,G_u(n-1)\) 即可。计算 \(f_{v,X-S-1}\) 时需要拉插。
最终满足条件的方案数就是 \(G_u(S)\)。设总方案数为 \(C\),那么答案为 \(1-\dfrac{G_u(S)}{C}\)。
时间复杂度为 \(\mathcal{O}(n^2)\)。
主要代码
int tc, n, k;
ll S, X;
int fa[MAXN], dep[MAXN], sz[MAXN];
vector<int> T[MAXN];
mint f[MAXN][MAXN], g[MAXN][MAXN];
mint fac[MAXN], ifac[MAXN];
mint pre[MAXN], suf[MAXN];
void init(int n) {
fac[0] = 1;
for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i;
ifac[n] = fac[n].inv();
for (int i = n - 1; i >= 0; --i) ifac[i] = ifac[i + 1] * (i + 1);
}
mint calc(mint *a, mint x, int n) {
pre[0] = 1;
for (int i = 1; i <= n; ++i) pre[i] = pre[i - 1] * (x - i + 1);
suf[n] = 1;
for (int i = n - 1; i >= 0; --i) suf[i] = suf[i + 1] * (x - i - 1);
mint res = 0;
for (int i = 0; i <= n; ++i) res += a[i] * pre[i] * suf[i] * ifac[i] * ifac[n - i] * (n - i & 1 ? -1 : 1);
return res;
}
void dfs1(int u) {
sz[u] = 1;
for (int v : T[u]) {
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
}
}
void dfs2(int u) {
if (T[u].empty()) {
for (int i = 0; i < n; ++i) {
f[u][i] = i + 1;
g[u][i] = 1;
}
return;
}
fill(f[u], f[u] + n, 1);
fill(g[u], g[u] + n, 1);
for (int v : T[u]) {
dfs2(v);
for (int i = 0; i < n; ++i) f[u][i] *= f[v][i];
mint val = calc(f[v], X - S - 1, sz[v]);
for (int i = 0; i < n; ++i) {
if (i) g[v][i] += g[v][i - 1];
g[u][i] *= val + (dep[v] < k ? g[v][i] : 0);
}
}
for (int i = 1; i < n; ++i) f[u][i] += f[u][i - 1];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init(MAXN - 5);
cin >> tc;
while (tc--) {
cin >> n >> k >> S >> X;
for (int i = 1; i <= n; ++i) T[i].clear();
for (int i = 2; i <= n; ++i) {
cin >> fa[i];
T[fa[i]].emplace_back(i);
}
dfs1(1);
if (*max_element(dep + 1, dep + n + 1) < k) {
cout << "0\n";
continue;
}
if (X <= S) {
cout << "1\n";
continue;
}
dfs2(1);
for (int i = n - 1; i; --i) f[1][i] -= f[1][i - 1];
cout << 1 - calc(g[1], S, n - 1) / calc(f[1], X, n - 1) << '\n';
}
return 0;
}

浙公网安备 33010602011771号