BC#65T4 ZYB's Tree
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5593
点分治被卡了TAT。。。 正解是dp,可以按层数考虑dp,先预处理跑一边dfs得到子树各层数点数大小,再dfs一遍找出不在子树上的与当前点距离<=k的点。
设u为当前点,v为其一个儿子,有g[v][1]=1
g[v][i]+=g[u][i-1](i>=2)
g[v][i]+=f[u][i-1]-f[v][i-2](i>=2)
完全不难嘛比赛的时候人都傻了TAT,还是太弱了
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstdlib> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 500500 #define ll long long using namespace std; int f[maxn][12],g[maxn][12],head[maxn],n,k,ans,tot; struct data{int obj,pre; }e[maxn]; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)){ if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void insert(ll x,ll y){ e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot; } void dfs(int u){ f[u][0]=1; for (int j=head[u];j;j=e[j].pre){ int v=e[j].obj; dfs(v); rep(i,1,k) f[u][i]+=f[v][i-1]; } } void dfs2(int u){ int sum=0; rep(i,0,k) sum+=f[u][i]; for (int j=head[u];j;j=e[j].pre){ int v=e[j].obj; g[v][1]=1; rep(i,2,k) g[v][i]+=g[u][i-1]; rep(i,2,k) g[v][i]+=f[u][i-1]-f[v][i-2]; dfs2(v); } rep(i,1,k) sum+=g[u][i]; ans^=sum; } int main(){ int t; scanf("%d",&t); while (t--){ clr(g,0); clr(f,0); clr(head,0); tot=0; ll a,b; n=read(); k=read(); scanf("%lld%lld",&a,&b); rep(i,2,n){ ll now=(ll)i; ll f=(a*now+b)%(now-1)+1; insert(f,i); } ans=0; dfs(1); dfs2(1); printf("%d\n",ans); } return 0; }