zoukankan      html  css  js  c++  java
  • HDU-5909 Tree Cutting

    Description

    Byteasar has a tree (T) with (n) vertices conveniently labeled with (1,2,...,n). Each vertex of the tree has an integer value (v_i).

    The value of a non-empty tree (T) is equal to (v_1oplus v_2oplus ...oplus v_n), where (oplus) denotes bitwise-xor.

    Now for every integer (k) from ([0,m)), please calculate the number of non-empty subtree of (T) which value are equal to (k).

    A subtree of (T) is a subgraph of (T) that is also a tree.

    Input

    The first line of the input contains an integer (T(1leq Tleq10)), denoting the number of test cases.

    In each test case, the first line of the input contains two integers (n(nleq 1000)) and (m(1leq mleq 2^{10})), denoting the size of the tree (T) and the upper-bound of (v).

    The second line of the input contains (n) integers (v_1,v_2,v_3,...,v_n(0leq v_i < m)), denoting the value of each node.

    Each of the following (n-1) lines contains two integers (a_i,b_i), denoting an edge between vertices (a_i) and (b_i(1leq a_i,b_ileq n)).

    It is guaranteed that (m) can be represent as (2^k), where (k) is a non-negative integer.

    Output

    For each test case, print a line with (m) integers, the (i)-th number denotes the number of non-empty subtree of (T) which value are equal to (i).

    The answer is huge, so please module (10^9+7).

    Sample Input

    2
    4 4
    2 0 1 3
    1 2
    1 3
    1 4
    4 4
    0 1 3 1
    1 2
    1 3
    1 4
    

    Sample Output

    3 3 2 3
    2 4 2 3
    

    题意

    求一颗树中异或值为([0,m))的联通块数量

    题解

    我们先考虑暴力.

    (f[u][j])为必须选择u结点,异或和为j的方案数,那么有(f[u][ioplus j]=f[u][i]*f[v][j]),由于是求所有联通块,而这个答案其实是选择v的联通块的方案数,所以我们还需要把之前的方案数再加回来,也就是

    [tmp[j]=f[u][j](j:0...m)\f[u][ioplus j]=f[u][i]*f[v][j](i:0...m,j:0...m)\f[u][j] += tmp[j](j:0...m) ]

    而中间的(f[u][ioplus j]=f[u][i]*f[v][j])可以使用fwt优化,从而使(n^2)的转移降到(nlogn),这样总复杂度(n^2logn),可以通过

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 1e9 + 7;
    ll qpow(ll a, ll b) {
        ll ans = 1;
        while (b) {
            if (b & 1) ans = ans * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return ans;
    }
    const ll inv2 = qpow(2, mod - 2);
    void fwt_xor(ll a[], int len, int op) {
        for (int h = 2; h <= len; h <<= 1) {
            for (int j = 0; j < len; j += h) {
                for (int k = j; k < j + h / 2; k++) {
                    ll u = a[k], t = a[k + h / 2];
                    a[k] = (u + t) % mod;
                    a[k + h / 2] = (u - t + mod) % mod;
                    if (op == -1) {
                        a[k] = a[k] * inv2 % mod;
                        a[k + h / 2] = a[k + h / 2] * inv2 % mod;
                    }
                }
            }
        }
    }
    const int N = 2050;
    vector<int> G[N];
    ll f[N][N * 2];
    ll tmp[N * 2];
    int n, m;
    int c[N];
    ll ans[N * 2];
    void dfs(int u, int fa) {
        f[u][c[u]] = 1;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (v == fa) continue;
            dfs(v, u);
            for (int j = 0; j < m; j++) {
                tmp[j] = f[u][j];
            }
            fwt_xor(f[u], m, 1);
            fwt_xor(f[v], m, 1);
            for (int j = 0; j < m; j++) {
                f[u][j] = f[u][j] * f[v][j] % mod;
            }
            fwt_xor(f[u], m, -1);
            for (int j = 0; j < m; j++) {
                f[u][j] = (f[u][j] + tmp[j]) % mod;
            }
        }
        for (int j = 0; j < m; j++) {
            ans[j] = (ans[j] + f[u][j]) % mod;
        }
    
    }
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
    
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j < m; j++) {
                    f[i][j] = 0;
                    ans[j] = 0;
                }
            }
    
            for (int i = 1; i <= n; i++) {
                scanf("%d", &c[i]);
                G[i].clear();
            }
            for (int i = 1; i < n; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs(1, 0);
            for (int i = 0; i < m - 1; i++) {
                printf("%lld ", ans[i]);
            }
            printf("%lld
    ", ans[m - 1]);
        }
        return 0;
    }
    
  • 相关阅读:
    php CodeIgniter处理多环境错误级别配置
    bootstrap导航条在手机上默认展开二级目录,必须用setTimeout才能实现
    WordPress博客网站fonts.useso加载慢解决办法
    JS实现复制网页内容自动加入版权内容代码和原文链接
    bootstrap实现 手机端滑动效果,滑动到下一页,jgestures.js插件
    mysql字段varchar区分大小写utf8_bin、utf8_general_ci编码区别
    js捕捉IE窗口失去焦点事件,判断离开页面刷新或关闭的方法
    php防盗链,php ci在control里面控制除了自己站内的链接点击跳转,其他来源的都跳到站内页面
    php原子操作,文件锁flock,数据库事务
    默认只显示指定高度,出来按钮 阅读更多,加载全文,点击后显示全文的实现方式
  • 原文地址:https://www.cnblogs.com/artoriax/p/12188030.html
Copyright © 2011-2022 走看看