CF855C Helga Hufflepuff's Cup
Floating_Trees · · 题解
思路
计数题,考虑 dp。
考虑每个节点转移需要直到的条件:
- 儿子节点所染的颜色与
k 的大小关系。 - 已经有多少个点的颜色为
k 。
那么我们就根据这个设计状态
如果
如果
如果
于是我们列出转移方程:
需要注意转移的时候
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, p = 1e9 + 7;
int n, m, k, maxk, sz[N];
long long f[N][20][3], g[20][3];
vector<int> E[N];
void dfs(int u, int fa)
{
// 边界情况
f[u][0][0] = k - 1, f[u][1][1] = 1, f[u][0][2] = m - k, sz[u] = 1;
for (int v : E[u]) if (v != fa)
{
dfs(v, u);
// 处理重复的问题
for (int i = 0;i <= min(sz[u], maxk);i++)
g[i][0] = f[u][i][0], g[i][1] = f[u][i][1], g[i][2] = f[u][i][2],
f[u][i][0] = f[u][i][1] = f[u][i][2] = 0;
// 转移
for (int i = 0;i <= min(sz[u], maxk);i++)
for (int j = 0;j <= sz[v] && i + j <= maxk;j++)
f[u][i+j][0] = (f[u][i+j][0] + g[i][0] * (f[v][j][0] + f[v][j][1] + f[v][j][2]) % p) % p,
f[u][i+j][1] = (f[u][i+j][1] + g[i][1] * f[v][j][0] % p) % p,
f[u][i+j][2] = (f[u][i+j][2] + g[i][2] * (f[v][j][0] + f[v][j][2]) % p) % p;
sz[u] += sz[v]; // 注意要先转移在加上大小,否则变为 O(n^2)
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m;
for (int i = 1, u, v;i < n;i++)
cin >> u >> v, E[u].emplace_back(v), E[v].emplace_back(u);
cin >> k >> maxk;
dfs(1, 0);
long long ans = 0;
for (int i = 0;i <= min(maxk, n);i++)
ans = (ans + f[1][i][0] + f[1][i][1] + f[1][i][2]) % p; // 统计答案
cout << ans << "\n";
return 0;
}