BZOJ3696 化合物

我们可以树形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
", ans[i]);
71     return 0;
72 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4352046.html