传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5909

【题解】

设$f_{x,i}$表示以$x$节点的子树中,权值为$i$的子树个数,其中$x$必选。

那么有dp方程:$f_{x,i} = \sum_{y = son[x]} f_{x,i} + \sum_{j \oplus k = i}f_{x, j}f_{y, k}$

用FWT优化转移即可,复杂度$O(nmlogm)$。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e3 + , H = + ;
const int mod = 1e9+; int n, L, w[N], inv2;
int f[N][H];
int ans[H];
int head[N], nxt[N + N], to[N + N], tot = ;
inline void add(int u, int v) {
++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}
inline void adde(int u, int v) {
add(u, v), add(v, u);
} inline int pwr(int a, int b) {
int ret = ;
while(b) {
if(b&) ret = 1ll * ret * a % mod;
a = 1ll * a * a % mod;
b >>= ;
}
return ret;
} int s[H], t[H];
inline void FWT(int *a, int op) {
if(op) {
for (int len = ; len <= L; len<<=) {
int m = len >> ;
for (int *p = a; p != a+L; p += len) {
for (int k=; k<m; ++k) {
int x = p[k], y = p[k+m];
p[k] = 1ll * (x+y) * inv2 % mod;
p[k+m] = 1ll * (x-y+mod) * inv2 % mod;
}
}
}
} else {
for (int len = ; len <= L; len<<=) {
int m = len >> ;
for (int *p = a; p != a+L; p += len) {
for (int k=; k<m; ++k) {
int x = p[k], y = p[k+m];
p[k] = (x+y) % mod;
p[k+m] = (x-y+mod) % mod;
}
}
}
}
} inline void FWT_combine(int *A, int *B) {
for (int i=; i<L; ++i) s[i] = A[i], t[i] = B[i];
FWT(s, ); FWT(t, );
for (int i=; i<L; ++i) s[i] = 1ll * s[i] * t[i] % mod;
FWT(s, );
for (int i=; i<L; ++i) (A[i] += s[i]) %= mod;
} inline void dfs(int x, int fa = ) {
for (int j=; j<L; ++j) f[x][j] = ;
f[x][w[x]] = ;
for (int i=head[x]; i; i=nxt[i]) {
if(to[i] == fa) continue;
dfs(to[i], x);
FWT_combine(f[x], f[to[i]]);
}
for (int j=; j<L; ++j) (ans[j] += f[x][j]) %= mod;
} inline void sol() {
tot = ;
memset(head, , sizeof head);
memset(ans, , sizeof ans);
cin >> n >> L;
for (int i=; i<=n; ++i) scanf("%d", w+i);
for (int i=, u, v; i<n; ++i) {
scanf("%d%d", &u, &v);
adde(u, v);
}
dfs();
printf("%d", ans[]);
for (int i=; i<L; ++i) printf(" %d", ans[i]);
puts("");
} int main() {
int T; cin >> T;
inv2 = pwr(, mod-);
while(T--) sol();
return ;
}

最新文章

  1. 自定义鼠标光标cursor
  2. windosw应用提示内存不足
  3. meta标签的用法
  4. Linux内核学习笔记
  5. C# 中的 lock的陷阱
  6. datetime 和 smalldatetime
  7. Foundation Data Structure
  8. JAVA试练塔之试炼技能图
  9. 201521123114 《Java程序设计》第12周学习总结
  10. 阿里巴巴分布式服务框架 Dubbo 介绍
  11. class文件魔数CAFEBABE的由来
  12. JS实现多语言方式
  13. LibreOJ 题解汇总
  14. foreman源NO_PUBKEY 6F8600B9563278F6
  15. FuelPHP 系列(四) ------ Validate 验证
  16. Python中的base64模块
  17. Layui 好用的弹出框
  18. iOS之富文本(一)
  19. Useful WCF Behaviors - IErrorHandler
  20. gitlab库迁移

热门文章

  1. c#笔记整理 关于继承与多态等
  2. c++ 第五次作业(计算器第三步)
  3. 理解BitSet
  4. Git 应用补丁报错 “sha1 information is lacking or useless”
  5. arp获取
  6. HDU 4869 Turn the pokers(思维+逆元)
  7. Android 常用dialog提示对话框
  8. POJ1204:Word Puzzles——题解
  9. 弱校的ACM奋斗史
  10. mac, xcode 6.1 安装command line tools 支持,autoconf,automake等