Processing math: 100%

【HDU5909】Tree Cutting FWT

f[x][j] 表示以 x 为根的子树,选出连通块的异或值为 j 的方案数.

然后有 f[x][j]=f[x][j]+ik=jf[x][i]×f[son][k].

其中, 为异或符号.

求解这个东西显然可以用 FWT 来加速.

有两种方式,第一个是当遍历 x 的儿子的时候分别于每一个儿子都做一次 FWT,但是这个会比较慢.

一个更好的方式是我们知道若干个多项式相乘不必一一相乘,而是统一进行 FWT,然后最后做一次 IFWT 就行.

但是这里有一个地方需要注意:f[x][0] 必须要 +1,因为当 x 的父亲与 x 结合时有可能不选 x.     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <cstdio>
#include <cstring>
#include <string>  
#include <vector> 
#include <cctype>  
#include <algorithm> 
#define N 1306 
#define RG register
#define ll long long
#define mod 1000000007
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;   
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
int lim,inv,n;     
int f[N][N],ans[N];   
vector<int>G[N];  
int qpow(int x,int y)
{
    int tmp=1;
    for(;y;y>>=1,x=(ll)x*x%mod)
        if(y&1) tmp=(ll)tmp*x%mod; 
    return tmp;
}
void FWT(int *a,int opt)
{
    int i,j,k; 
    for(i=1;i<lim;i<<=1)
    {
        for(j=0;j<lim;j+=i<<1)
        {
            for(k=0;k<i;++k)
            {
                int tmp=a[j+k];  
                a[j+k]=(ll)(a[j+k]+a[j+k+i])%mod;      
                a[j+k+i]=(ll)(tmp-a[j+k+i]+mod)%mod;    
                if(opt==-1)
                {
                    a[j+k]=(ll)inv*a[j+k]%mod;  
                    a[j+k+i]=(ll)inv*a[j+k+i]%mod;  
                }  
            }
        }
    }
}
void dfs(int u,int ff)
{
    FWT(f[u],1);
    for(int i=0;i<G[u].size();++i)
    {
        int y=G[u][i];
        if(y==ff) continue;  
        dfs(y,u);   
        for(int j=0;j<lim;++j) f[u][j]=(ll)f[u][j]*f[y][j]%mod;  
    }                  
    FWT(f[u],-1),f[u][0]=(f[u][0]+1)%mod,FWT(f[u],1);            
    G[u].clear(); 
}
int main()
{
    // setIO("input"); 
    inv=qpow(2,mod-2); 
    int i,j,T; 
    T=read(); 
    while(T--)
    
        // scanf("%d%d",&n,&lim);    
        n=read(),lim=read();
        memset(f,0,sizeof(f)),memset(ans,0,sizeof(ans));  
        for(i=1;i<=n;++i)
        {
            ++f[i][read()];  
        }
        for(i=1;i<n;++i)
        {
            int x=read(),y=read(); 
            G[x].push_back(y);
            G[y].push_back(x);  
        }  
        dfs(1,0); 
        for(i=1;i<=n;++i)  FWT(f[i],-1);  
        for(i=1;i<=n;++i)  f[i][0]=(f[i][0]-1+mod)%mod;          
        for(i=1;i<=n;++i)  for(j=0;j<lim;++j) ans[j]=(ll)(ans[j]+f[i][j])%mod;  
        for(i=0;i<lim-1;++i) printf("%d ",ans[i]);  
        printf("%d\n",ans[lim-1]);   
    }
    return 0;
}

  

posted @   EM-LGH  阅读(112)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示