化合物 bzoj-3696
题目大意:给你一棵树,定义两个点i , j之间的A值是(dis[i]-dis[lca(i,j)])xor(dis[j]-dis[lca(i,j)])。对所有的k$\in$[1,n],A值等于k的点对数量。
注释:$1\le n\le 10^5$,$1\le maxdis \le 500$。
想法:说什么异或意义下的母函数,完全不会(具体数学没看完的垃圾蒟蒻)。其实就是个暴力...
我们设dp[pos][i]表示以pos为根,长度为i的链的个数,然后直接转移。每次$H^2$扫,复杂度$O(N\cdot 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\n",ans[i]); return 0; }
小结:这种题,不指望自己考试能切了
原文地址:https://www.cnblogs.com/ShuraK/p/9255351.html
时间: 2024-10-07 05:30:33