我们可以树形dp...
令f[p][d]表示以p为根的子树,与p距离为d的结点数
然后我们计算答案:
一种是从某个节点q到根p的方案,对和为d的贡献是1
另一种是p的一个子树中的节点x到另一个子树中的节点y的方案,对和为d[x] ^ d[y]的贡献为1
第二种我们可以通过f暴力求出,话说什么时候去研究一下FWT啊。。。
1 /************************************************************** 2 Problem: 3696 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:476 ms 7 Memory:207460 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 1e5 + 5; 15 const int H = 525; 16 17 struct edge { 18 int next, to; 19 edge() {} 20 edge(int _n, int _t) : next(_n), to(_t) {} 21 } e[N]; 22 23 int n; 24 int first[N], tot; 25 int f[N][H], ans[H], dep[N]; 26 27 inline int read() { 28 int x = 0, sgn = 1; 29 char ch = getchar(); 30 while (ch < ‘0‘ || ‘9‘ < ch) { 31 if (ch == ‘-‘) sgn = -1; 32 ch = getchar(); 33 } 34 while (‘0‘ <= ch && ch <= ‘9‘) { 35 x = x * 10 + ch - ‘0‘; 36 ch = getchar(); 37 } 38 return sgn * x; 39 } 40 41 inline void Add_Edge(int x, int y) { 42 e[++tot] = edge(first[x], y), first[x] = tot; 43 } 44 45 #define y e[x].to 46 void dfs(int p) { 47 int x, i, j; 48 f[p][0] = 1; 49 for (x = first[p]; x; x = e[x].next) { 50 dfs(y); 51 for (i = 0; i <= dep[p]; ++i) 52 for (j = 0; j <= dep[y]; ++j) 53 ans[i ^ (j + 1)] += f[p][i] * f[y][j]; 54 dep[p] = max(dep[p], dep[y] + 1); 55 for (i = 0; i <= dep[y]; ++i) 56 f[p][i + 1] += f[y][i]; 57 } 58 } 59 #undef y 60 61 int main() { 62 int i, mx; 63 n = read(); 64 for (i = 2; i <= n; ++i) 65 Add_Edge(read(), i); 66 dfs(1); 67 for (mx = H - 1; mx; --mx) 68 if (ans[mx]) break; 69 for (i = 0; i <= mx; ++i) 70 printf("%d\n", ans[i]); 71 return 0; 72 }
原文:http://www.cnblogs.com/rausen/p/4352046.html