zoukankan      html  css  js  c++  java
  • 「CF995F」Cowmpany Cowmpensation

    传送门

    题目大意就是给你一颗有根树,每个点的权值可以是 ([1, D]) 的任意一个数,需要满足一个节点的权值不比它的父亲的大,求不同赋值情况的方案数。

    首先我们可以考虑一个比较显然的 (O(nD)) 做法:

    考虑 ( ext{DP}),设 (dp_{u, j}) 表示 (u) 的子树的方案,其中 (u) 的权值不超过 (j)

    初始状态 (dp_{u, j} = 1),考虑每一颗 (u) 的子树 (v),我们每次都把 (dp_{u, j}) 乘上 (dp_{v, j})。然后这些方案是有包含关系的,所以还要前缀和一下。

    那么我们现在就可以求出 (ans_i = dp_{1, i}, i in [1, n])

    可以证明 (ans_i) 是一个关于 (i) 的不超过 (i + 1) 次的多项式。

    那么我们就直接拉格朗日插值一下就好了。

    参考代码:

    #include <cstdio>
    
    const int _ = 3002, p = 1e9 + 7;
    
    int tot, head[_]; struct Edge { int v, nxt; } edge[_];
    inline void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }
    
    int n, k, dp[_][_], ans;
    
    inline int power(int x, int k) {
        int s = 1;
        for (; k; k >>= 1, x = 1ll * x * x % p)
            if (k & 1) s = 1ll * s * x % p;
        return s % p;
    }
    
    inline void dfs(int u) {
        for (int i = 1; i <= n; ++i) dp[u][i] = 1;
        for (int i = head[u]; i; i = edge[i].nxt) {
            int v = edge[i].v; dfs(v);
            for (int j = 1; j <= n; ++j)
                dp[u][j] = 1ll * dp[u][j] * dp[v][j] % p;
        }
        for (int i = 1; i <= n; ++i) dp[u][i] = (dp[u][i] + dp[u][i - 1]) % p;
    }
    
    inline int Lagrange() {
        int ans = 0;
        for (int i = 0; i <= n; ++i) {
            int s1 = dp[1][i], s2 = 1;
            for (int j = 0; j <= n; ++j)
                if (i != j) {
                    s1 = 1ll * s1 * ((k - j + p) % p) % p;
                    s2 = 1ll * s2 * ((i - j + p) % p) % p;
                }
            ans = (ans + 1ll * s1 * power(s2, p - 2)) % p;
        }
        return ans;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
    #endif
        scanf("%d %d", &n, &k);
        for (int x, i = 2; i <= n; ++i) scanf("%d", &x), Add_edge(x, i);
        dfs(1);
        if (k <= n) printf("%d
    ", dp[1][k]);
        else printf("%d
    ", Lagrange());
        return 0;
    }
    
  • 相关阅读:
    2016.7.31整机升级计划
    UVa 1588
    UVa1587
    Jzoj4714 公约数
    Jzoj4714 公约数
    Jzoj4713 A
    Jzoj4713 A
    Jzoj4711 Binary
    Jzoj4711 Binary
    Jzoj4710 Value
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/13138273.html
Copyright © 2011-2022 走看看