CF280C Game on Tree
阿新 • • 發佈:2022-03-22
蒟蒻初學概率與期望
這道題感覺非常玄幻 (雖然在大佬眼裡只是一道水題)
思路
我們設 \(f_i\) 表示 \(i\) 被刪除時選擇了 \(i\) 的次數
顯然 \(f_i=0/1\)
那麼題目要求的其實就是 \(E(\sum f_i)\)
而有因為期望滿足可加性
因此我們考慮求單個點的貢獻 \(E(f_i)\)
顯然,只有在恰好選到 \(i\) 點時,它才會有貢獻,且為恰好選到 \(i\) 的概率
這就要求我們之前都不能選擇 \(i\) 的祖先結點
那它的概率怎麼算?一個很妙的想法,就是將樹上的結點轉化成一個序列,而選點就是每次選擇一個最前面的數,將它以及它子樹內的數都去掉
那麼要恰好選擇到 \(i\)
根據排列組合,這個概率顯然是 \(\frac{1}{dep_i}\)(\(dep_i\) 表示 \(i\) 的深度,也就是 \(i\) 祖先樹 +1)
最後將所有都加起來即可
程式碼
#include<iostream> #include<fstream> #include<algorithm> #include<cmath> #include<cstdlib> #include<cstring> #include<queue> #include<map> #include<set> #include<bitset> #define LL long long inline int reads() { int sign = 1, re = 0; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();} while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();} return sign * re; } int n, cnt; double ans; struct Node { int to, next; }r[200005]; int he[100005]; inline void dfs(int now, int de, int fa) { ans += 1.0 / de; for(int i = he[now]; i; i = r[i].next) if(r[i].to != fa) dfs(r[i].to, de + 1, now); } signed main() { #ifndef ONLINE_JUDGE freopen("test.in", "r", stdin); freopen("test.out", "w", stdout); #endif n = reads(); for(int i = 1; i < n; i++) { int u = reads(), v = reads(); r[++cnt] = (Node){v, he[u]}, he[u] = cnt; r[++cnt] = (Node){u, he[v]}, he[v] = cnt; } dfs(1, 1, 0); printf("%.7lf", ans); return 0; }