题面传送门

出题人可能原本感觉没啥难度的 T2 竟然变成了防 AK 题,奇迹奇迹(

首先带着这个 \(\max\) 肯定不太好处理,考虑找出 \(f(S)\) 的等价表达。我们考虑以 \(1\) 为根 DFS 一遍整棵树,然后考虑贪心。每次贪心地找到所有路径中 LCA 最深的路径,如果这条路径上所有节点都没被访问过我们就将该路径上所有节点都设为被访问过并令答案加一,否则我们直接不管这条路径。感性理解一下可知我们采取这样的策略肯定能取到较多的路径。

接下来考虑求答案的事。考虑方案数转期望,我们求出每个点有多大概率作为某个被选择路径的 LCA 出现过,然后把它们加起来再乘上 \(2^{n^2}\) 就是答案。那么怎么求呢?注意到对于一个点如果它的某个祖先被访问了,那么这个点也没有用了。因此我们可以将选择一条路径视作直接将这个子树吃掉(虽然这样说好像有点奇怪?),这样就可以 DP 了,我们设 \(dp_{u,j}\) 表示钦定了 LCA 在 \(u\) 子树内的路径,还有 \(j\) 个点没有被吃掉的概率,转移就将两个子树合并起来即可,设 \(u\) 为 \(v\) 的父亲,那么显然 \(dp_{u,0}\) 只能转移到新的 \(dp_{u,0}\),而对于 \(i\ne 0\),\(j\in[0,siz_y]\),\(dp_{u,i}\) 和 \(dp_{v,j}\) 有 \(\dfrac{1}{2^{2ij}}\) 的概率转移到 \(dp_{u,i+j}\),有 \(1-\dfrac{1}{2^{2ij}}\) 的概率转移到 \(dp_{u,0}\)。树上背包求一下即可。最终 \(dp_{i,0}\) 即为 \(i\) 作为某条路径 LCA 出现的概率。时间复杂度 \(\mathcal O(n^2)\)。

总结:为什么这样的题目要找出 \(f(S)\) 的等价表达?因为这里的 \(f(S)\) 是一个找最大值的形式,而求一车东西的 \(\max\) 这个东西是很难计算的(当然有些情况下确实是可以,不过要用 Min-Max 容斥等技巧,并且局限性比较大),(当然有的数据范围很小的题目也可以用这个做法,比方说一些 DP 套 DP,如 TJOI2018 游园)。因此我们需要想办法将其转化为求和的形式,这时候就要找到它的等价表达。类似的题目还有 CF1067E Random Forest Rank。

const int MAXN=5000;
const int INV2=MOD+1>>1;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int n,ipw2[MAXN*MAXN+5],dp[MAXN+5][MAXN+5],res=0,siz[MAXN+5];
link_list<int,MAXN,MAXN*2> g;
void dfs(int x,int f){
dp[x][0]=dp[x][1]=INV2;siz[x]=1;
for(int e=g.hd[x];e;e=g.nxt[e]){
int y=g.val[e];if(y==f) continue;dfs(y,x);
static int tmp[MAXN+5];memset(tmp,0,sizeof(tmp));
for(int i=1;i<=siz[x];i++) for(int j=0;j<=siz[y];j++){
tmp[i+j]=(tmp[i+j]+1ll*dp[x][i]*dp[y][j]%MOD*ipw2[2*i*j])%MOD;
tmp[0]=(tmp[0]+1ll*dp[x][i]*dp[y][j]%MOD*(1-ipw2[2*i*j]+MOD))%MOD;
} siz[x]+=siz[y];for(int i=1;i<=siz[x];i++) dp[x][i]=tmp[i];
dp[x][0]=(dp[x][0]+tmp[0])%MOD;
} res=(res+dp[x][0])%MOD;//printf("%d %d\n",x,dp[x][0]);
}
int main(){
freopen("thousands.in","r",stdin);
freopen("thousands.out","w",stdout);
scanf("%d",&n);
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),g.ins(u,v),g.ins(v,u);
for(int i=(ipw2[0]=1);i<=n*n;i++) ipw2[i]=1ll*ipw2[i-1]*INV2%MOD;
dfs(1,0);printf("%d\n",1ll*res*qpow(2,n*n)%MOD);
return 0;
}

最新文章

  1. iOS开发_内存泄漏、内存溢出和野指针之间的区别
  2. Irrelevant Elements, ACM/ICPC NEERC 2004, UVa1635
  3. Python 小游戏 Bunny
  4. mysql事务处理的意义
  5. .Net程序员学习Linux(三)
  6. linux下查看文件系统类型
  7. HDU2149-Public Sale
  8. Entity Framework 丢失数据链接的绑定,在已绑好的EDMX中提示“Choose Your Data Connection”
  9. js 循环 常用方法
  10. 微信公众号tp3.2放进Model无效,几种实例化的方法试过,还是提示无法提供服务
  11. IDEA zookeeper插件的使用
  12. [Swift]LeetCode692. 前K个高频单词 | Top K Frequent Words
  13. Linux shell if判断语句
  14. SUI-mobile起步
  15. oracle 删除重复数据
  16. 浅谈我的UI设计之路
  17. 【Thinkphp5】封装layer弹窗方法
  18. 20145319 《网络渗透》Adobe阅读器渗透攻击
  19. sonar安装问题记录
  20. python 基于udp 连接

热门文章

  1. 【UE4 设计模式】观察者模式 Observer Pattern
  2. 第2次 Beta Scrum Meeting
  3. springBoot服务整合线程池ThreadPoolTaskExecutor与@Async详解使用
  4. Ubuntu下在当前用户下安装JDK1.8
  5. 彻底搞通TCP滑动窗口
  6. 如何减小微信小程序代码包大小
  7. Red Hat Enterprise Linux (RHEL) 9 更新了什么,即 Rocky Linux 9 和 AlmaLinux 9 展望
  8. #web开发# 知道cookie hostonly属性的请举手。
  9. webpack 之开发环境优化 HMR
  10. pyinstaller设置图标出现“struct.error: unpack requires a buffer of 16 bytes”