zoukankan      html  css  js  c++  java
  • 【BZOJ-3696】化合物 树形DP + 母函数(什么鬼)

    3696: 化合物

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 165  Solved: 85
    [Submit][Status][Discuss]

    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

    Solution

    神奇的树形DP,表示自己只会暴力...

    然后去看题解了.... 折越

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define maxn 100010
    int n,fa[maxn],ans[600],dp[maxn][600],size[maxn];
    struct EdgeNode{int next,to;}edge[maxn];
    int head[maxn],cnt;
    void add(int u,int v)
    {
        cnt++;
        edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;
    }
    void DFS(int now)
    {
        dp[now][0]=1;
        for (int i=head[now]; i; i=edge[i].next)
            {
                DFS(edge[i].to);
                for (int j=0; j<=size[now]; j++)
                    for (int k=0; k<=size[edge[i].to]; k++)
                        ans[j^(k+1)]+=dp[now][j]*dp[edge[i].to][k];
                if (size[edge[i].to]+1>size[now]) size[now]=size[edge[i].to]+1;
                for (int j=0; j<=size[edge[i].to]; j++)
                    dp[now][j+1]+=dp[edge[i].to][j];
            }
    }
    int main()
    {
        n=read();
        for (int i=2; i<=n; i++) fa[i]=read(),add(fa[i],i);
        DFS(1);
        int sz=599; while (sz--) if (ans[sz]!=0) break;
        for (int i=0; i<=sz; i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    hdu2328 Corporate Identity
    hdu1238 Substrings
    hdu4300 Clairewd’s message
    hdu3336 Count the string
    hdu2597 Simpsons’ Hidden Talents
    poj3080 Blue Jeans
    poj2752 Seek the Name, Seek the Fame
    poj2406 Power Strings
    hust1010 The Minimum Length
    hdu1358 Period
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5513345.html
Copyright © 2011-2022 走看看