CF696B Puzzles 期望
阿新 • • 發佈:2018-10-21
algorithm bin for color fin str ios || getc
顯然可以樹形$dp$
令$f[i]$表示$i$號節點的期望時間戳
不妨設$fa$有$k$個子節點,對於$i$的子節點$u$,它是第$j(1 \leqslant j \leqslant k)$個被訪問的概率是相同的,為$\frac{1}{k}$
當它作為第$j$個子節點被訪問時,需要從剩下的$k - 1$個節點中挑出$j - 1$個放到它前面,對每種情況的$sz$和取期望
考慮貢獻法
一個節點$v$,會給第$j$個被訪問的節點的貢獻次數為$\binom{k - 2}{j - 2}$
總的貢獻次數為$\binom{k - 1}{j - 1}$
因此,第$v$個節點對第$j$個被訪問的節點的貢獻為$\frac{j - 1}{k - 1} * sz[v]$
也就是說$u$節點在所有情況下需要被耽誤的時間應該為$\sum\limits_{1 \leqslant i \leqslant k} \frac{i - 1}{k - 1} * \sum sz[v]$
其中,$v$表示除了$u$以外的所有子節點
化簡一番,也就是$f[v] = f[fa] + 1 + \frac{1}{2} * \sum sz[v]$
$O(n)$即可
#include <map> #include <set> #include <queue> #include <vector> #include <cstdio> #include<cstring> #include <iostream> #include <algorithm> namespace remoon { #define de double #define le long double #define ri register int #define tpr template <typename ra> #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++) #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --) #definegc getchar inline int read() { int p = 0, w = 1; char c = gc(); while(c > ‘9‘ || c < ‘0‘) { if(c == ‘-‘) w = -1; c = gc(); } while(c >= ‘0‘ && c <= ‘9‘) p = p * 10 + c - ‘0‘, c = gc(); return p * w; } } using namespace std; using namespace remoon; #define sid 300050 de f[sid]; int n, sz[sid]; vector <int> son[sid]; inline void dfs(int o, int fa) { sz[o] = 1; for(auto cur : son[o]) dfs(cur, o), sz[o] += sz[cur]; } inline void dfs(int o) { for(auto cur : son[o]) { f[cur] = f[o] + 1 + (sz[o] - sz[cur] - 1) / 2.0; dfs(cur); } } int main() { n = read(); rep(i, 2, n) son[read()].pb(i); dfs(1, 0); f[1] = 1; dfs(1); rep(i, 1, n) printf("%lf ", f[i]); return 0; }
CF696B Puzzles 期望