您的位置:首页 > 其它

bzoj 3696 化合物 解题报告

2017-07-19 21:17 288 查看

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

思路

枚举每个点暴力。。。???还真是奇特的数据。。。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=100000+5;
const int M=500+5;
int n,num,a
[M],ans[M],head
,deep
,maxn=M;
struct edge
{
int v,next;
};
edge ed
;
void build(int u,int v)
{
ed[++num].v=v;
ed[num].next=head[u];
head[u]=num;
}
void dfs(int x)
{
a[x][0]=1;
for (int i=head[x];i;i=ed[i].next)
{
dfs(ed[i].v);
for (int j=0;j<=deep[x];j++)
for (int k=0;k<=deep[ed[i].v];k++)
ans[j^(k+1)]+=a[x][j]*a[ed[i].v][k];
deep[x]=max(deep[x],deep[ed[i].v]+1);
for (int j=0;j<=deep[ed[i].v];j++)
a[x][j+1]+=a[ed[i].v][j];
}
}
int main()
{
scanf("%d",&n);
for (int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
build(x,i);
}
dfs(1);
while(maxn>0) {maxn--;if (ans[maxn]) break;}
for (int i=0;i<=maxn;i++)
printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: