Newcoder 156 F.托米的遊戲(樹形)
阿新 • • 發佈:2018-12-12
Description
托米有一棵有根樹, 樹根為,每輪他會在剩下的子樹中等概率一個點, 砍掉的子樹 (包含),如果樹上的點都被砍光了,遊戲結束。
求出這個遊戲進行的期望輪數,可以證明這個數一定是有理數,設他為,你需要告訴他一個整數滿足
Input
第一行輸入一個數, 表示的點數,下面行給出了的每條邊
Output
一行一個整數表示答案
Sample Input
3 1 2 1 3
Sample Output
2
Solution
輪數的期望即為每個點被選中的概率之和,對於點,若選取非到根節點路徑上的點不會影響選中的概率,而當選取到根節點路徑上非節點時點會被刪掉,故選中點的概率即為從到根節點路徑上所有點中選出的概率,也即,其中為節點的深度(假設根節點深度為),故只要求出每點深度即可
Code
#include<cstdio> #include<vector> using namespace std; typedef long long ll; #define maxn 100005 #define mod 998244353 int mul(int x,int y) { ll z=1ll*x*y; return z-z/mod*mod; } int add(int x,int y) { x+=y; if(x>=mod)x-=mod; return x; } int n,dep[maxn],inv[maxn]; vector<int>g[maxn]; void dfs(int u,int fa) { for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(v==fa)continue; dep[v]=dep[u]+1; dfs(v,u); } } int main() { scanf("%d",&n); inv[1]=1; for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v),g[v].push_back(u); } dep[1]=1; dfs(1,0); int ans=0; for(int i=1;i<=n;i++)ans=add(ans,inv[dep[i]]); printf("%d\n",ans); return 0; }