zoukankan      html  css  js  c++  java
  • [bzoj3696]化合物_树形dp

    化合物 bzoj-3696

    题目大意:给你一棵树,定义两个点i , j之间的A值是(dis[i]-dis[lca(i,j)])xor(dis[j]-dis[lca(i,j)])。对所有的k$in$[1,n],A值等于k的点对数量。

    注释:$1le nle 10^5$,$1le maxdis le 500$。

    想法:说什么异或意义下的母函数,完全不会(具体数学没看完的垃圾蒟蒻)。其实就是个暴力...

    我们设dp[pos][i]表示以pos为根,长度为i的链的个数,然后直接转移。每次$H^2$扫,复杂度$O(Ncdot H^2)$,然后... ...就过了。

    最后,附上丑陋的代码... ...

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

    小结:这种题,不指望自己考试能切了

  • 相关阅读:
    第三次作业-有进度条圆周率计算
    第一周作业
    24点
    Cuber Sorting
    P1827 [USACO3.4]美国血统 American Heritage
    P4387 【深基15.习9】验证栈序列
    P2058 海港
    P4017 最大食物链计数
    P2196 挖地雷
    放苹果问题
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9255351.html
Copyright © 2011-2022 走看看