题意:
给一棵有n个节点,根为1的树的每个节点赋一个值 1-n 的唯一的值。一个子树的代表是其中最大的节点。则一共有m个代表,求m=k的方案数。
思路:
多校题。。这样的dp还是不太会。。
1) u是一个代表 等价于 u是以他为根的子树的最大值
2)有k个代表 等价于 有且只有k个子树,根为该子树中的最大值
sz[u]表示 u的子树大小
dp[i][j]表示 1-i 节点有j棵子树根为最大值
dp[i][j]=dp[i−1][j]∗(1−sz[i])/sz[i]+dp[i−1][j−1]/sz[i]
int n, k, sz[N];
LL dp[N][N], Pw[N];
vector<int> graph[N];
void dfs(int fa, int u) {
sz[u] = 1;
for (int v:graph[u])
if ( v != fa ) {
dfs(u, v);
sz[u] += sz[v];
}
}
LL fast_pow(LL x, int n) {
LL ret = 1;
while (n) {
if (n&1) ret = ret * x % Mod;
n >>= 1;
x = x * x % Mod;
}
return ret;
}
LL inv(LL x) {
return fast_pow(x, Mod-2);
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
Pw[0] = 1; rep(i, 1, 1000) Pw[i] = Pw[i-1] * i % Mod;
int t, cas = 0;
scanf("%d", &t);
while(t--) {
++ cas;
scanf("%d%d", &n, &k);
rep(i, 0, n-1) graph[i].clear();
rep(i, 1, n-1) {
int u, v;
scanf("%d%d", &u, &v);
-- u, -- v;
graph[u].push_back(v);
graph[v].push_back(u);
}
dfs(-1, 0);
dp[0][0] = 1;
rep(i, 1, n) {
LL p = inv(sz[i-1]);
LL q = (sz[i-1] - 1) * p % Mod;
dp[i][0] = dp[i-1][0] * q % Mod;
rep(j, 1, k) {
dp[i][j] = (dp[i-1][j] * q + dp[i-1][j-1] * p) % Mod;
}
}
LL ans = Pw[n] * dp[n][k] % Mod;
printf("Case #%d: %I64d\n", cas, ans);
}
return 0;
}