参考博客

https://www.cnblogs.com/Mychael/p/9255572.html

https://www.cnblogs.com/cjyyb/p/9065611.html

题意:给定一棵无根树,统计所有子树的异或和的个数。

dp[u][i],表示u为根的数,xor值得到i的方案数

显然,每次合并就是两个dp    dp值做xor   xor卷积

利用FWT优化异或卷积

然后被卡常

链式前向星更快

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define swap(a,b) (a^=b^=a^=b)
const ll maxn=2050;
const ll mod= 1e9+7;
ll inv2;
ll a[1<<17],b[1<<17],c[1<<17],N;
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
inline void FWT_xor(ll *a,ll f)
{
    register ll i,j,p,k;
    for(i=1; i<N; i<<=1)for(p=i<<1,j=0; j<N; j+=p)for(k=0; k<i; ++k)
            {
                ll X=a[j+k],Y=a[i+j+k];
                a[j+k]=(X+Y)%mod;
                a[i+j+k]=(X+mod-Y)%mod;
                if(f==-1)a[j+k]=1ll*a[j+k]*inv2%mod,a[i+j+k]=1ll*a[i+j+k]*inv2%mod;
            }
}
ll qpow(ll a,ll n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)
            ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
ll dp[maxn][maxn];
vector<ll>v[maxn];
ll val[maxn];
void dfs(ll n,ll fa)
{
    dp[n][val[n]]=1;
    FWT_xor(dp[n],1);
    for(ll i=0; i<v[n].size(); i++)
    {
        if(v[n][i]==fa)
            continue;
        ll to=v[n][i];
        dfs(to,n);
        //FWT_xor(dp[to],1);
        for(ll j=0; j<N; j++)
        {
            dp[n][j]=dp[n][j]*(dp[to][j]+1)%mod;
        }
        //FWT_xor(dp[to],-1);
    }
    //FWT_xor(dp[n],-1);
}

int main()
{
    inv2=qpow(2,mod-2);
    ll t,n,m,x,y;
    scanf("%lld",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        for(ll i=0; i<maxn; i++)
            v[i].clear();
        n=read();
        m=read();
        N=1;
        while(N<=m)N<<=1;
        for(ll i=1; i<=n; i++)
        {
            val[i]=read();
        }
        for(ll i=0; i<n-1; i++)
        {
            x=read();
            y=read();
            v[x].push_back(y);
            v[y].push_back(x);
        }
        dfs(1,0);
        for(ll i=1;i<=n;i++)
              FWT_xor(dp[i],-1);
        for(ll i=0; i<m; i++)
        {
            ll ans=0;
            for(ll j=1; j<=n; j++)
            {
                ans+=dp[j][i];
                ans%=mod;
            }
            printf("%lld",ans);
            if(i!=m-1)
                printf(" ");
        }
        printf("\n");
    }
    return 0;
}