1 条题解
-
0
自动搬运
来自洛谷,原作者为

Bulyly
09年在役选手搬运于
2025-08-24 22:48:09,当前版本为作者最后更新于2023-06-11 19:48:38,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
- 很合胃口的一道题。
-
考虑枚举每个点 为 LCA 时对方案数产生的贡献。显然此时满足要求的点应该在 的子树当中。将其子树中点对形成的 LCA 分为 与非 两类。
-
根据鸽巢原理可得,一个符合条件的 元组应该最多只能出现 个 LCA 为非 类。于是问题转换为找非 两类集合的数量。
-
更进一步,显然以子节点为根的树中任意点对才是非 类的,所以一个子树中我们最多可选 个。令 表示以 为 LCA ,再子树中取 个点的方案数。答案为 。用树上背包实现。
下附代码:
#include<bits/stdc++.h> using namespace std; using ll=long long; const int N=5010,mod=1e9+7; int n,p,k; vector<int> e[N]; int sz[N]; int f[N][N]; ll ans; void dfs(int u,int fa) { sz[u]=1,f[u][0]=f[u][1]=1; for(int j:e[u]) { if(j==fa) continue; dfs(j,u); int psz=sz[u]; sz[u]+=sz[j]; for(int d=min(sz[u],p);d>=1;d--) for(int t=max(1,d-psz);t<=min(min(k-1,d),sz[j]);t++) f[u][d]+=1ll*f[u][d-t]*f[j][t]%mod, f[u][d]%=mod; } ans+=f[u][p]; ans%=mod; } int main() { scanf("%d%d%d",&n,&p,&k); for(int i=1;i<n;i++) { int a,b; cin>>a>>b; e[a].push_back(b); e[b].push_back(a); } dfs(1,-1); cout<<ans<<endl; }完结撒花~
- 1
信息
- ID
- 8773
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者