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_1\oplus v_2\oplus ...\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(1\leq T\leq10)\), denoting the number of test cases.

In each test case, the first line of the input contains two integers \(n(n\leq 1000)\) and \(m(1\leq m\leq 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(0\leq 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(1\leq a_i,b_i\leq 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

The meaning of problems

Seeking the exclusive OR tree is \ ([0, m) \ ) Number of blocks Unicom

answer

We first consider the violence.

Set \ (F [u] [j] \) must be chosen u node, exclusive OR, and as the number of program j is, then there is \ (f [u] [i \ oplus j] = f [u] [i] f * [v] [J] \) , because it is to do everything Unicom blocks, and the answer is actually the number of program choices v Unicom block, so the number of programs before we also need to come back together, that is,
\ [tmp [j] = f [u] [j] (j: 0 ... m) \\ f [u] [i \ oplus j] = f [u] [i] * f [v] [j] (i : 0 ... m, j: 0
... m) \\ f [u] [j] + = tmp [j] (j: 0 ... m) \] and the middle \ (f [u] [i \ oplus j] = f [u] [i] * f [v] [j] \) may be used fwt optimized so that \ (n ^ 2 \) was transferred down \ (nlogn \) , so the total complexity \ (n-2logn ^ \) , by

Code

#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\n", ans[m - 1]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/artoriax/p/12188030.html