HDU 5909,FWT

Tree Cutting

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

The value of a non-empty tree T is equal to v1⊕v2⊕…⊕vn, where ⊕ 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≤T≤10), denoting the number of test cases.

In each test case, the first line of the input contains two integers n(n≤1000) and m(1≤m≤210), denoting the size of the tree T and the upper-bound of v.

The second line of the input contains n integers v1,v2,v3,…,vn(0≤vi<m), denoting the value of each node.

Each of the following n−1 lines contains two integers ai,bi, denoting an edge between vertices ai and bi(1≤ai,bi≤n).

It is guaranteed that m can be represent as 2k, 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.

题意: 有一颗树T有n个节点,每个节点有一个权值v,树T的子树定义为T的子图并且是一棵树,(为了区别,将子树的原定义称作子树1,题中的定义称作子树2),一颗子树2的权值为其所有节点v值的异或起来,现问对于所有k 属于 [1,m),有多少子树2的权值等于k

思路: 现需求出所有子树2的权值,考虑以u号节点作为根节点的子树1,定义tmp[u]为一个多项式,第i项表示以u号节点作为根节点的子树1能够产生的权值为i的子树2的数量,首先因为u号节点本身能构成一颗子树2,故 t m p [ u ] [ v [ u ] ] tmp[u][v[u]] 初始为1,然后考虑与u节点相邻的所有节点v1,v2,…,现如果已经求出tmp[v1],tmp[v2]…,那么它们所能够产生的子树2都能够与u节点相连后形成新的子树,但它也可以不和u相连,故对所有vi, + + t m p [ v i ] [ 0 ] ++tmp[vi][0] ,即表示vi不加入u的情况,然后tmp[v1] ^ tmp[v2] ^ … ^ tmp[u]即求出了tmp[u],直接FWT即可

#include<bits/stdc++.h>
#define MAXM 1500
#define MAXN 1005
using namespace std;
const int MOD = 1e9+7;
inline int qpow(int a,int b,int mod)
{
    int ans = 1;
    while(b)
    {
        if(b & 1) ans = 1ll * ans * a % mod;
        a = 1ll * a * a % mod;
        b >>= 1;
    }
    return ans;
}
int tot,head[MAXN];
struct edge
{
    int v,nxt;
}edg[MAXN << 1];
inline void addedg(int u,int v)
{
    edg[tot].v = v;
    edg[tot].nxt = head[u];
    head[u] = tot++;
}
int n,m,val[MAXN];
int len,inv2;
inline void FWT_xor(int *A,int on)
{
    for(int i = 1;i < len;i <<= 1) for(int p = i<<1,j = 0;j < len;j += p)
        for(int k = 0;k < i;++k)
        {
            int x = A[j+k],y = A[i+j+k];
            A[j+k] = (x+y)%MOD,A[i+j+k] = (x+MOD-y) % MOD;
            if(on == -1) A[j+k] = 1ll*A[j+k]*inv2%MOD,A[i+j+k] = 1ll*A[i+j+k]*inv2%MOD;
        }
}
inline void init()
{
    memset(head,-1,sizeof(int)*(n+1));
    tot = 0;
}
int ans[MAXM<<1],tmp[MAXN][MAXM<<1];
void dfs(int u,int f)
{
    for(int i = 0;i < len;++i)
        tmp[u][i] = 0;
    ++tmp[u][val[u]];
    FWT_xor(tmp[u],1);
    for(int i = head[u];i != -1;i = edg[i].nxt)
    {
        int v = edg[i].v;
        if(v != f)
        {
            dfs(v,u);
            FWT_xor(tmp[v],1);
            for(int i = 0;i < len;++i)
                tmp[u][i] = 1ll * tmp[u][i] * tmp[v][i] % MOD;
        }
    }
    FWT_xor(tmp[u],-1);
    for(int i = 0;i < len;++i)
        ans[i] = (ans[i] + tmp[u][i])%MOD;
    ++tmp[u][0];
}
int main()
{
    int t;
    inv2 = qpow(2,MOD-2,MOD);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;++i)
            scanf("%d",&val[i]);
        int u,v;
        init();
        for(int i = 1;i < n;++i)
        {
            scanf("%d%d",&u,&v);
            addedg(u,v);
            addedg(v,u);
        }
        len = 1;
        while(len <= m) len <<=1;
        memset(ans,0,sizeof(ans));
        dfs(1,1);
        for(int i = 0;i < m-1;++i)
            printf("%d ",ans[i]);
        printf("%d\n",ans[m-1]);
    }
    return 0;
}//
发布了50 篇原创文章 · 获赞 3 · 访问量 3117

猜你喜欢

转载自blog.csdn.net/xing_mo/article/details/103966019
FWT
hdu