HDU5593 ZYB's Tree 树形DP +分治

时间:2021-11-19 18:14:17

感觉其实就是树分治,一次BC的题,感觉这次题目质量比较高,仅代表蒟蒻的看法

一次DFS获取每个点到子树的距离不大于K的点的个数,

然后一遍BFS获取从每个点父亲不大于K的的个数,层层扩展,还是想说 其实就是树分治。。。。。并没有什么DP

/*
Problem : 5593 ( ZYB's Tree ) Judge Status : Accepted
RunId : 15764784 Language : G++ Author : qianbi08
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstdlib>
#include<queue>
using namespace std;
const int maxn=;
int head[maxn],fa[maxn],p;
int dp[maxn][],n,k,a,b;
struct Edge
{
int v,next;
}edge[maxn*];
void addedge(int u,int v)
{
edge[p].v=v;
edge[p].next=head[u];
head[u]=p++;
}
void dfs(int u)
{
dp[u][]=;
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa[u])continue;
dfs(v);
for(int j=;j<=k;j++)
dp[u][j]+=dp[v][j-];
}
}
queue<int>q;
void bfs()
{
while(!q.empty())q.pop();
for(int i=head[];~i;i=edge[i].next)
q.push(edge[i].v);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=k;i>;--i)
dp[u][i]+=dp[fa[u]][i-]-dp[u][i-];
++dp[u][];
for(int i=head[u];~i;i=edge[i].next)
if(edge[i].v!=fa[u])q.push(edge[i].v);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&n,&k,&a,&b);
memset(head,-,sizeof(head));
memset(dp,,sizeof(dp));
p=;
fa[]=;
long long aa=a;
for(int i=;i<=n;i++)
{
aa+=a;
int u=(aa+b)%(i-)+;
int v=i;
fa[v]=u;
addedge(u,v);
addedge(v,u);
}
dfs();
bfs();
int ans;
for(int i=;i<=n;i++)
{
int sum=;
for(int j=;j<=k;j++)
sum+=dp[i][j];
if(i==)ans=sum;
else ans^=sum;
}
printf("%d\n",ans);
}
return ;
}