zoukankan      html  css  js  c++  java
  • [HEOI 2013]SAO

    Description

    题库连接

    给你一个 (n) 个节点的有向树,问你这棵树的拓扑序个数,对大质数取模。多测,测试组数 (T)

    (1leq nleq 1000, 1leq Tleq 5)

    Solution

    以 1 为根。记 (f_{u,i}) 表示 (u) 为根的子树中 (u) 的拓扑序号为 (i) 时的方案数。

    从儿子 (v) 向父亲 (u) 转移时,考虑 ((u,v)) 的方向。以 (u ightarrow v) 为例。

    枚举 (u) 的拓扑序号 (i)(v) 的拓扑序 (j)。那么 (u,v) 的分别的原排列如图示((A,B) 为原先在 (u) 前/后的部分,(C,D) 同理),

    [ egin{aligned} underline{quad Aquad}&quad iquadunderline{quad Bquad}\ & downarrow\ underline{quad Cquad}&quad jquadunderline{quad Dquad} end{aligned} ]

    我们考虑 (u) 在新序列中的位置 (k),可以得到

    [ ext{new}f_{u,k} = sum_{i,j}{k-1choose i-1}{sz_u+sz_v-kchoose sz_u-i}f_{u,i}f_{v,j} ]

    其中 (sz_u) 表示子树 (u) 的大小。

    容易发现 (j) 这一维可以前缀和优化。

    故最终复杂度为 (O(n^2))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int yzh = 1000000007, N = 1000+5;
    
    int f[N][N], sz[N], t, n, u, v, g[N], fac[N], ifac[N];
    struct tt {
        int to, nxt, c;//0->
    } edge[N<<1];
    int path[N], top;
    char sign;
    
    int C(int n, int m) {return 1ll*fac[n]*ifac[m]%yzh*ifac[n-m]%yzh; }
    void dfs(int u, int fa) {
        f[u][1] = sz[u] = 1;
        for (int v, i = path[u]; i; i = edge[i].nxt)
            if ((v = edge[i].to) != fa) {
                dfs(v, u);
                memcpy(g, f[u], sizeof(g));
                memset(f[u], 0, sizeof(g));
                if (edge[i].c == 0) {
                    for (int i = 1; i <= sz[u]; i++)
                        for (int k = i; k <= i+sz[v]-1; k++)
                            (f[u][k] += 1ll*C(k-1, i-1)*C(sz[u]+sz[v]-k, sz[u]-i)%yzh*g[i]%yzh*(f[v][sz[v]]-f[v][k-i])%yzh) %= yzh;
                } else {
                    for (int i = 1; i <= sz[u]; i++)
                        for (int k = i+1; k <= i+sz[v]; k++)
                            (f[u][k] += 1ll*C(k-1, i-1)*C(sz[u]+sz[v]-k, sz[u]-i)%yzh*g[i]%yzh*f[v][k-i]%yzh) %= yzh;               
                }
                sz[u] += sz[v];
            }
        for (int i = 1; i <= n; i++) (f[u][i] += f[u][i-1]) %= yzh;
    }
    void add(int u, int v, int c) {
        edge[++top] = (tt){v, path[u], c};
        path[u] = top;  
    }
    int main() {
        n = 1000;
        ifac[0] = ifac[1] = fac[0] = 1;
        for (int i = 2; i <= n; i++) ifac[i] = -1ll*yzh/i*ifac[yzh%i]%yzh;
        for (int i = 1; i <= n; i++)
            ifac[i] = 1ll*ifac[i]*ifac[i-1]%yzh,
            fac[i] = 1ll*i*fac[i-1]%yzh;
        scanf("%d", &t);
        while (t--) {
            scanf("%d", &n); top = 0;
            for (int i = 1; i <= n; i++) {
                path[i] = sz[i] = 0;
                for (int j = 1; j <= n; j++) f[i][j] = 0;
            }
            for (int i = 1; i < n; i++) {
                scanf("%d %c %d", &u, &sign, &v); ++u, ++v;
                if (sign == '<') add(u, v, 0), add(v, u, 1);
                else add(u, v, 1), add(v, u, 0);
            }
            dfs(1, 0);
            printf("%d
    ", (f[1][n]+yzh)%yzh);
        }
        return 0;
    }
  • 相关阅读:
    webpack 打包性能分析工具
    npm 使用
    npm 构建时,次要版本变化引起的问题
    AtomicStampedReference、AtomicMarkableReference 区别
    vue-cli 中的静态资源处理
    vue-cli 构建项目中 config/index.js 文件解读
    webpack的3个路径配置项: assetsRoot、assetsSubDirectory、assetsPublicPath
    Vue2 dist 目录下各个文件的区别
    DllPlugin、DllReferencePlugin 可以提取的第三方库列表
    JUC集合之 CopyOnWriteArrayList
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/12236218.html
Copyright © 2011-2022 走看看