HDU 5378 Leader in Tree Land (概率dp,进阶)

本文探讨了如何通过动态规划解决在树结构中计算具有特定节点数量代表的方案数的问题。详细介绍了多校题解题思路,包括节点赋值、最大值与代表节点的关系、子树大小的计算以及动态规划状态转移方程的建立。并通过实例展示了从根节点到所有节点的遍历过程,以及最终求解方案数的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
给一棵有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[i1][j](1sz[i])/sz[i]+dp[i1][j1]/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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值