【概率期望】發電機

【描述】
石室中學因爲資源不足,供電成爲很大的問題。爲了改善人民的生活,石室中學的王子ZxY決定爲他 的王國發明一種新型的發電機!
首先,石室中學可以抽象成爲由 n 個點組成的一棵樹,其中 1 號點爲石室中學石室中學的首都。石室中學的城市 等級分明,除了首都之外,每個城市都有一個父級城市,也就是在樹上的父親。
ZxY 要使用他發明的發電機,就必須先選擇一個城市作爲發電中心,在這個城市安裝上發電 機後,這個城市會把電力供給給他,以及的他的父級城市一直到首都上的所有點。
有一天,石室中學又停電了,ZxY 決定用他的發電機爲全國供電。他每次會隨機選擇一個城市, 然後嘗試着爲這個城市安裝發電機。如果在這個城市安裝上發電機後,能爲至少一個之前沒有電 的城市供應上電,那麼ZxY 就會在這個城市安裝發電機。否則,ZxY 會再次隨機選擇一個城市, 繼續上面的過程。ZxY會不斷重複以上的過程,直到全國都供應上電爲止。
ZxY 想要先爲他的方案留下充足的預算,於是他問到你:他最後期望給多少個城市安裝了發 電機?
【輸入】
第一行一個數 n。
接下來一行 n − 1 個數,第 i 個數表示第 i + 1 號節點的父親。
【輸出】
輸出一行,表示ZxY 安裝發電機的期望次數,爲了方便,這裏只用輸出模 998244353 意義下的值。

【思路】

這題挺簡單的。首先根據期望的線性性,答案爲每個點安裝發電機的概率之和。我們考慮一個點什麼時候會有貢獻:對於一種所有點的排列,我們可以發現,一個點x產生貢獻當且僅當它子樹內所有點都排在它後面。顯然子樹內所有點成爲其相對順序的第一個的概率是相同的,所以貢獻爲1sizex\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";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章