【概率期望】发电机

【描述】
石室中学因为资源不足,供电成为很大的问题。为了改善人民的生活,石室中学的王子ZxY决定为他 的王国发明一种新型的发电机!
首先,石室中学可以抽象成为由 n 个点组成的一棵树,其中 1 号点为石室中学石室中学的首都。石室中学的城市 等级分明,除了首都之外,每个城市都有一个父级城市,也就是在树上的父亲。
ZxY 要使用他发明的发电机,就必须先选择一个城市作为发电中心,在这个城市安装上发电 机后,这个城市会把电力供给给他,以及的他的父级城市一直到首都上的所有点。
有一天,石室中学又停电了,ZxY 决定用他的发电机为全国供电。他每次会随机选择一个城市, 然后尝试着为这个城市安装发电机。如果在这个城市安装上发电机后,能为至少一个之前没有电 的城市供应上电,那么ZxY 就会在这个城市安装发电机。否则,ZxY 会再次随机选择一个城市, 继续上面的过程。ZxY会不断重复以上的过程,直到全国都供应上电为止。
ZxY 想要先为他的方案留下充足的预算,于是他问到你:他最后期望给多少个城市安装了发 电机?
【输入】
第一行一个数 n。
接下来一行 n − 1 个数,第 i 个数表示第 i + 1 号节点的父亲。
【输出】
输出一行,表示ZxY 安装发电机的期望次数,为了方便,这里只用输出模 998244353 意义下的值。

【思路】

这题挺简单的。首先根据期望的线性性,答案为每个点安装发电机的概率之和。我们考虑一个点什么时候会有贡献:对于一种所有点的排列,我们可以发现,一个点x产生贡献当且仅当它子树内所有点都排在它后面。显然子树内所有点成为其相对顺序的第一个的概率是相同的,所以贡献为 1 s i z e x \frac{1}{size_x}

#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=1e7+7,mod=998244353;
int n,m,a,b,c;
inline int red(){
    int re data=0;bool w=0; char ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return w?-data:data;
}
int fa[N],siz[N]={0,1},inv[N]={1,1},ans=0;
inline int mul(const int&a,const int&b){return 1ll*a*b%mod;}  
int main(){
	n=red();
	for(int re i=2;i<=n;i++)siz[i]=1,fa[i]=red(),inv[i]=mul(inv[mod%i],mod-mod/i);
	for(int re i=n;i;--i)siz[fa[i]]+=siz[i],((ans+=inv[siz[i]])>=mod)&&(ans-=mod);
	cout<<ans<<"\n";
}
发布了106 篇原创文章 · 获赞 22 · 访问量 5488

猜你喜欢

转载自blog.csdn.net/weixin_44111457/article/details/102654867