• #树形dp#C 树上排列


    题目


    分析

    (dp[x][i])表示以(x)为根的子树中(x)的排名为(i)的方案数,
    然后枚举子节点转移即可,Talk is cheap,Show me the code


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N = 3011, mod = 998244353;
    struct node {
        int y, w, next;
    } e[N << 1];
    int siz[N], dp[N][N], f[N], as[N], fac[N], inv[N], n, et = 1, ans;
    inline signed iut() {
        rr int ans = 0;
        rr char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
        return ans;
    }
    inline signed mo(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
    inline signed C(int n, int m) { return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod; }
    inline void dfs(int x, int fa) {
        siz[x] = dp[x][1] = 1;
        for (rr int i = as[x]; i; i = e[i].next)
            if (e[i].y != fa) {
                dfs(e[i].y, x);
                for (rr int j = 1; j <= siz[x]; ++j) f[j] = dp[x][j], dp[x][j] = 0;
                for (rr int j = 1; j <= siz[x]; ++j) {
                    rr int sum = 0;
                    if (e[i].w)
                        for (rr int o = siz[e[i].y]; ~o; --o)
                            dp[x][j + o] = mo(dp[x][j + o], 1ll * f[j] * C(j + o - 1, j - 1) % mod *
                                                                C(siz[x] + siz[e[i].y] - j - o, siz[x] - j) %
                                                                mod * sum % mod),
                                      sum = mo(sum, dp[e[i].y][o]);
                    else
                        for (rr int o = 0; o <= siz[e[i].y]; ++o)
                            sum = mo(sum, dp[e[i].y][o]),
                            dp[x][j + o] = mo(dp[x][j + o], 1ll * f[j] * C(j + o - 1, j - 1) % mod *
                                                                C(siz[x] + siz[e[i].y] - j - o, siz[x] - j) %
                                                                mod * sum % mod);
                }
                siz[x] += siz[e[i].y];
            }
    }
    signed main() {
        freopen("perm.in", "r", stdin);
        freopen("perm.out", "w", stdout);
        n = iut(), fac[0] = fac[1] = inv[0] = inv[1] = 1;
        for (rr int i = 2; i <= n; ++i) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
        for (rr int i = 2; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
        for (rr int i = 2; i <= n; ++i) inv[i] = 1ll * inv[i - 1] * inv[i] % mod;
        for (rr int i = 1; i < n; ++i) {
            rr int x = iut(), y = iut();
            e[++et] = (node){ y, 1, as[x] }, as[x] = et;
            e[++et] = (node){ x, 0, as[y] }, as[y] = et;
        }
        dfs(1, 0);
        for (rr int i = 1; i <= n; ++i) ans = mo(ans, dp[1][i]);
        return !printf("%d", ans);
    }
    
  • 相关阅读:
    编程作业4.1:神经网络反向传播(BP算法)
    700. Search in a Binary Search Tree
    671. Second Minimum Node In a Binary Tree
    653. Two Sum IV
    606. Construct String from Binary Tree
    590. N-ary Tree Postorder Traversal
    589. N-ary Tree Preorder Traversal
    617. Merge Two Binary Trees
    SHELL 变量
    egrep 正则表达式
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14038010.html
Copyright © 2020-2023  润新知