[3696]化合物

博弈论游戏与树形DP
本文介绍了一种基于树形结构的动态规划算法,用于解决一个涉及博弈论的化学问题。通过构建一种特殊的化合物分子树,算法计算了两两原子间的特定值对数,展示了树形DP的高效应用。

Description

    首长NOI惨跪,于是去念文化课了。现在,他面对一道化学题。
    这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏。这个游戏很蛋疼,我相信你们也没有兴趣听。
    由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值。
    他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节)。这个分子构成一个树结构,1号分子为根。    若两个原子i、j到它们的最近公共祖先的距离分别是Li和Lj,定义它们的Aij值为:
Aij=Li  xor Lj
题目要求对于每一个k(k∈N),求出两两A值为k的原子对个数。

Input

  第一行一个整数N。
  接下来N-1行,每行一个整数p,第新亍的整数表示第i个原子的父亲为p。

Output

从K=0开始,第k+1行输出两两A值为K的原子对个数,输出到第一个不为零的数为止。

Sample Input

3
1
1

Sample Output

1
2

HINT

【数据规模与约定】

用h表示树结构分子的最大深度。

 N<=10^5,H<=500

Source

暴力到突破天际的树形dp。。。啥都没得说

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #define M 100010
 4 #define ll long long
 5 using namespace std;
 6 struct point{int to,next;}e[M];
 7 int n,num;int head[M],maxd[M];ll ans[M],f[M][510];
 8 void add(int from,int to) {e[++num].next=head[from];e[num].to=to;head[from]=num;}
 9 void dfs(int x)
10 {
11     f[x][0]=1;
12     for(int i=head[x];i;i=e[i].next)
13     {
14         int to=e[i].to; dfs(to);
15         for(int j=0;j<=maxd[x];j++) for(int k=0;k<=maxd[to];k++)
16             ans[j^(k+1)]+=(ll)f[x][j]*f[to][k];
17         maxd[x]=max(maxd[x],maxd[to]+1);
18         for(int j=0;j<=maxd[to];j++) f[x][j+1]+=f[to][j];
19     }
20 }
21 int main()
22 {
23     scanf("%d",&n);
24     for(int i=2;i<=n;i++) {int x; scanf("%d",&x); add(x,i);} dfs(1);
25     int maxn=521;while(maxn--) if(ans[maxn]) break;
26     for(int i=0;i<=maxn;i++) printf("%lld\n",ans[i]);
27     return 0;
28 }

 

转载于:https://www.cnblogs.com/Slrslr/p/9603417.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值