「CF696B」Puzzle 题解 (期望与树形综合DP)

题目简介

给一颗树,按 dfs 序遍历并编号,对每个点求其编号的期望值。

分析

鄙人的想法与题解区稍微有点区别(尽管结论一样,过程却繁杂得多),希望不被大佬们嫌弃。

fx表示结点 x 的期望值,sizx表示以 x 为根的子树大小,考虑当前结点为 x 怎么向其子节点 y 转移。

xk 个儿子:

  • 假设在 x 选择的第一个结点就是 y ,那么 fy 将等于 fx+1,而概率是 1k

  • 假设在 x 选择的第一个结点不是 y ,第二个结点是 y ,那么 y(k1) 种不同的编号,分别是 fx+sizy+1(yy),因此总贡献为 (k1)×fx+sizy(yy)+(k1) ,每种的概率都是 (11k)×1k1×1k1=1k1×1k

  • 依此类推,假设 y 在第三个被选择,那么总贡献将为 (k2)×fx+2×sizy+(k2),相应的概率均为 1k2×1k

综上,可以得到一个状态转移方程:

fy=(fx+1)×1k+i=1k1(fx+sizy(yy)ni+1)×1k

这么去推肯定大大的TLE,考虑化简。

sizy(yy)=sizxsizy1

fy=(fx+1)×1k+i=1k1(fx+sizxsizy1ni+1)×1k

fy=(fx+1)×1k+i=1k1(fx+sizxsizy1i+1)×1k

fy=fx+1+i=1k1sizxsizy1i×1k

t=sizxsizy1

i=1k1ti×1k=t×i=1k11i×k=t×k(k1)2k(k1)=t2

由此得到转移:

fy=fx+sizxsizy12+1

AC Code

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
const int Maxn=1e5+5;
vector<int>tr[Maxn];
long double f[Maxn];
int siz[Maxn];
void dfs1(int x){
    siz[x]=1;
    for(auto y:tr[x]){
        dfs1(y);
        siz[x]+=siz[y];
    }
}
void dfs2(int x){
    for(auto y:tr[x]){
        f[y]=f[x]+1.0*(siz[x]-siz[y]-1)/2+1;
        dfs2(y);
    }
}
int main(){
    int n;cin>>n;
    for(int i=2;i<=n;++i){
        int x;cin>>x;
        tr[x].push_back(i);
    }
    f[1]=1;
    dfs1(1);dfs2(1);
    for(int i=1;i<=n;++i)printf("%.7Lf ",f[i]);
    return 0;
}

EOF

posted @   AlienCollapsar  阅读(30)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
// 生成目录索引列表 // ref: http://www.cnblogs.com/wangqiguo/p/4355032.html // modified by: zzq
点击右上角即可分享
微信分享提示