感觉其实就是树分治,一次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=500005; int head[maxn],fa[maxn],p; int dp[maxn][11],n,k,a,b; struct Edge { int v,next; }edge[maxn*2]; void addedge(int u,int v) { edge[p].v=v; edge[p].next=head[u]; head[u]=p++; } void dfs(int u) { dp[u][0]=1; 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=1;j<=k;j++) dp[u][j]+=dp[v][j-1]; } } queue<int>q; void bfs() { while(!q.empty())q.pop(); for(int i=head[1];~i;i=edge[i].next) q.push(edge[i].v); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=k;i>1;--i) dp[u][i]+=dp[fa[u]][i-1]-dp[u][i-2]; ++dp[u][1]; 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,-1,sizeof(head)); memset(dp,0,sizeof(dp)); p=0; fa[1]=0; long long aa=a; for(int i=2;i<=n;i++) { aa+=a; int u=(aa+b)%(i-1)+1; int v=i; fa[v]=u; addedge(u,v); addedge(v,u); } dfs(1); bfs(); int ans; for(int i=1;i<=n;i++) { int sum=0; for(int j=0;j<=k;j++) sum+=dp[i][j]; if(i==1)ans=sum; else ans^=sum; } printf("%d ",ans); } return 0; }