【HDU5909】Tree Cutting FWT
令 f[x][j] 表示以 x 为根的子树,选出连通块的异或值为 j 的方案数.
然后有 f[x][j]=f[x][j]+∑i⊕k=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; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步