zoukankan      html  css  js  c++  java
  • 4013: [HNOI2015]实验比较

    4013: [HNOI2015]实验比较

    链接

    分析:

      首先把等号用并查集合并起来。

      由于只存在最多一个质量不比i差的数,发现这是森林。若x<y,连边x->y。于是建虚拟根节点0。

      然后树形dp,f[i][j]表示第i棵子树内,分成了j段的方案数,即存在j-1个小于号。

      依次合并每个子树,假设一棵树内是a段,一棵树内是b段,合并后变成k段,$k in [max(a,b), a + b]$

      $f[i][k]=f[u][a] imes f[v][b] imes C_{k}^{a} imes C_{a}^{b-(k-a)}$

      后面一项的意义:此时相当于有k个盒子,有a个白球,b个黑球,每个盒子里不能同时出现两个黑球或者白球。那么先让每个白球选一个盒子放进去,黑球先补上空着的,最后多出的黑球放到以前白球的盒子里。

      复杂度:复杂度的话,看似O(N^4),但是,每个点对只会在其LCA处被枚举到并产生O(N)的运算量 精细地实现的话复杂度是O(N^3)的。by CRZbulabula 

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<cctype>
    #include<set>
    #include<map>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long LL;
     
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    inline int Read() {
        char ch = getchar();for(;ch!='<'&&ch!='='&&ch!='>'; ch=getchar());
        return (ch == '<' ? 1 : (ch == '=' ? 0 : 2));
    }
     
    const int N = 105, mod = 1e9 + 7;
    struct Edge { int to, nxt; } e[20005];
    int head[N], C[N][N], fa[N], ext[N][N], vis[N], deg[N], q[N], siz[N], f[N][N], tmp[N], En;
    vector<int> vec[N];
     
    inline void add_edge(int u,int v) {
        ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En; deg[v] ++;
    }
    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
    inline int mul(int x,int y) { return 1ll * x * y % mod; }
    void dfs(int u) {
        siz[u] = f[u][1] = 1;
        for (int I = head[u]; I; I = e[I].nxt) {
            int v = e[I].to;
            dfs(v);
            for (int i = 0; i < siz[u]; ++i) 
                for (int j = 1; j <= siz[v]; ++j)    
                    for (int k = max(i, j); k <= i + j; ++k) {
                        int A = mul(f[u][i + 1], f[v][j]), B = mul(C[k][i], C[i][j - k + i]);
                        add(tmp[k + 1], mul(A, B));
                    }
            siz[u] += siz[v];
            for (int i = 0; i <= siz[u]; ++i) f[u][i] = tmp[i], tmp[i] = 0;      
        }
    }
    int main () {
        int n = read(), m = read();
        C[0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            C[i][0] = 1;
            for (int j = 1; j <= i; ++j) 
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
        }
        for (int i = 1; i <= n; ++i) fa[i] = i;
        for (int i = 1; i <= m; ++i) {
            int x = read(), ty = Read(), y = read();
            if (!ty) {
                x = find(x), y = find(y);
                if (x != y) fa[x] = y;
            }
            else if (ty == 1) vec[x].push_back(y);
            else vec[y].push_back(x);
        }
        for (int i = 1; i <= n; ++i) {
            int x = find(i);
            for (int sz = vec[i].size(), j = 0; j < sz; ++j) {
                int y = find(vec[i][j]);
                if (!ext[x][y]) add_edge(x, y), ext[x][y] = 1;
            }
        }
        for (int i = 1; i <= n; ++i) 
            if (deg[i] == 0 && fa[i] == i) add_edge(0, i);
        int L = 1, R = 0;
        q[++R] = 0;
        while (L <= R) {
            int u = q[L ++]; vis[u] = 1;
            for (int i = head[u]; i; i = e[i].nxt) {
                int v = e[i].to;
                if (!(--deg[v])) q[++R] = v;
            }
        }
        for (int i = 1; i <= n; ++i) 
            if (fa[i] == i && !vis[i]) { cout << 0; return 0; }
        dfs(0);
        int ans = 0;
        for (int i = 1; i <= siz[0]; ++i) add(ans, f[0][i]);
        cout << ans;
        return 0;
    }
  • 相关阅读:
    windows下 安装 rabbitMQ 及操作常用命令
    C#中关于DataGridView行和列的背景色-前景色设置
    使用Linq判断DataTable数据是否重复
    C#用mouse_event模拟鼠标点击的问题
    ApartmentState.STA
    使用WebBrowser,内存一直增加的解决办法
    HOT SUMMER 每天都是不一样,积极的去感受生活 C#关闭IE相应的窗口 .
    您访问的URL地址不被允许。
    CMSIS-DAP for STLink V2.1 and STLink v2.1 mini adapter
    DG449 High Voltage Single SPDT Analog Switch in SOT23-8
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10355670.html
Copyright © 2011-2022 走看看