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,故 初始为1,然后考虑与u节点相邻的所有节点v1,v2,…,现如果已经求出tmp[v1],tmp[v2]…,那么它们所能够产生的子树2都能够与u节点相连后形成新的子树,但它也可以不和u相连,故对所有vi, ,即表示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;
}//