BZOJ-3696: 化合物

[文章目录]

Description

这个分子构成一个树结构,1号分子为根。 若两个原子i、j到它们的最近公共祖先的距离分别是Li和Lj,定义它们的Aij值为:Aij=Li xor Lj 题目要求对于每一个k(k∈N),求出两两A值为k的原子对个数。

不知道为什么,自带十倍常数。。。另外岷县跑不过的时间复杂度居然还是正解。。。
树形dp,num[x][i]表示以x为根长度为i的链的个数。然后每次暴力h方扫,另外将循环至循环到最深的节点的深度。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,num[100010][510],ans[1024];
int head[101000],to[101000],nxt[101000],cnt;
void add(int x,int y)
{
    to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;
}
int dfs(int x)
{
    int i,j,k,mx=0; num[x][0]=1;
    for(i=head[x];i;i=nxt[i])
    {
        int tmp=dfs(to[i])+1; mx=max(mx,tmp);
        for(j=1;j<=tmp;++j)
            for(k=0;k<=mx;++k)
                ans[k^j]+=num[x][k]*num[to[i]][j-1];
        for(j=1;j<=tmp;++j) num[x][j]+=num[to[i]][j-1];
    }
    return mx;
}
int main()
{
    scanf("%d",&n); int i,x;
    for(i=2;i<=n;++i)
    {
        scanf("%d",&x);
        add(x,i);
    }
    dfs(1); int now;
    for(i=512;i>=0;i--) if(ans[i]){ now=i; break; }
    for(i=0;i<=now;++i) printf("%d\n",ans[i]);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注