Tree Cutting

Tree Cutting

Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 262144/131072 K (Java/Others)
Problem Description

Byteasar has a tree TTT with nnn vertices conveniently labeled with 1,2,...,n1,2,...,n1,2,...,n. Each vertex of the tree has an integer value viv_ivi​​.

The value of a non-empty tree TTT is equal to v1⊕v2⊕...⊕vnv_1oplus v_2oplus ...oplus v_nv1​​v2​​...vn​​, where ⊕oplus⊕ denotes bitwise-xor.

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

A subtree of TTT is a subgraph of TTT that is also a tree.

Input

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

In each test case, the first line of the input contains two integers n(n≤1000)n(nleq 1000)n(n1000) and m(1≤m≤210)m(1leq mleq 2^{10})m(1m210​​), denoting the size of the tree TTT and the upper-bound of vvv.

The second line of the input contains nnn integers v1,v2,v3,...,vn(0≤vi<m)v_1,v_2,v_3,...,v_n(0leq v_i < m)v1​​,v2​​,v3​​,...,vn​​(0vi​​<m), denoting the value of each node.

Each of the following n−1n-1n1 lines contains two integers ai,bia_i,b_iai​​,bi​​, denoting an edge between vertices aia_iai​​ and bi(1≤ai,bi≤n)b_i(1leq a_i,b_ileq n)bi​​(1ai​​,bi​​n).

It is guaranteed that mmm can be represent as 2k2^k2k​​, where kkk is a non-negative integer.

Output

For each test case, print a line with mmm integers, the iii-th number denotes the number of non-empty subtree of TTT which value are equal to iii.

The answer is huge, so please module 109+710^9+7109​​+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

分析:dp[i][j]表示以i为根异或值为j的方案数;
   在加入i的儿子x的子树方案时,dp[i][j]=dp[i][j]+dp[i][k]*dp[x][t](k^t=j);

   其中dp[i][k]*dp[x][t](k^t=j)的复杂度为n²,可以用异或卷积加速到nlogn;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <list>
#define vi vector<int>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
#define mod 1000000007
#define rev (mod+1)/2
#define inf 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
using namespace std;
const int maxn=1e3+30;
int n,m,k,t,a[maxn],dp[maxn][maxn],tmp[maxn],ans[maxn];
vi e[maxn];
void fwt(int *a,int n)
{
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++)
            {
                int x=a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
            }
}
void ufwt(int *a,int n)
{
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++)
            {
                int x=a[i+j],y=a[i+j+d];
                a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
            }
}
void solve(int *a,int *b,int n)
{
    fwt(a,n);
    fwt(b,n);
    for(int i=0;i<n;i++)a[i]=1LL*a[i]*b[i]%mod;
    ufwt(a,n);
}
void dfs(int now,int pre)
{
    dp[now][a[now]]=1;
    for(int x:e[now])
    {
        if(x==pre)continue;
        dfs(x,now);
        for(int i=0;i<m;i++)
            tmp[i]=dp[now][i];
        solve(dp[now],dp[x],m);
        for(int i=0;i<m;i++)
            dp[now][i]=(dp[now][i]+tmp[i])%mod;
    }
    for(int i=0;i<m;i++)
        ans[i]=(ans[i]+dp[now][i])%mod;
}
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        rep(i,1,n)
        {
            scanf("%d",&a[i]),e[i].clear();
            rep(j,0,m-1)dp[i][j]=0;
        }
        rep(i,0,m-1)ans[i]=0;
        rep(i,1,n-1)
        {
            scanf("%d%d",&j,&k);
            e[j].pb(k),e[k].pb(j);
        }
        dfs(1,0);
        rep(i,0,m-1)printf("%d%c",ans[i],i<m-1?' ':'
');
    }
    //system ("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/dyzll/p/5938446.html