[2019徐州网络赛J题]Random Access Iterator
大致题意:从根节点出发,在节点x有son[x]次等概率进入儿子节点,求到达最深深度的概率。son[x]为x节点的儿子节点个数。
又又又又没做出来,心态崩了。
下来看了官方题解后发觉自己大体思路是没错的,但是细节太弱了Orz。
大体思路:设dp[x]为以x为根节点,求到达最深深度的概率。先跑一遍dfs,求出每个点的子节点数,每个点的深度以及最深深度。
我们可以求得从x点一次不能到达最深深度的概率为$cnt =1-(\tfrac{\sum_{y\epsilon x } dp[y]}{son[x]})$
则$dp[x]=1-cnt^{son[x]}$为son[x]次能到达最深深度的概率。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e6 + 10; 5 const ll mod = 1e9 + 7; 6 struct node { 7 int s, e, next; 8 }edge[maxn]; 9 int head[maxn], len; 10 void init() { 11 memset(head, -1, sizeof(head)); 12 len = 0; 13 } 14 void add(int s, int e) { 15 edge[len].e = e; 16 edge[len].next = head[s]; 17 head[s] = len++; 18 } 19 int mxd[maxn], d[maxn], son[maxn]; 20 ll dp[maxn]; 21 ll qpow(ll a, ll b, ll mod) { 22 ll ans = 1; 23 while (b) { 24 if (b & 1)ans = ans * a % mod; 25 a = a * a % mod; 26 b >>= 1; 27 } 28 return ans; 29 } 30 void dfs(int x, int fa) { 31 mxd[x] = d[x]; 32 for (int i = head[x]; i != -1; i = edge[i].next) { 33 int y = edge[i].e; 34 if (y == fa)continue; 35 d[y] = d[x] + 1; 36 son[x]++; 37 dfs(y, x); 38 mxd[x] = max(mxd[x], mxd[y]); 39 } 40 } 41 void dfs1(int x, int fa) { 42 ll sum = 0; 43 for (int i = head[x]; i != -1; i = edge[i].next) { 44 int y = edge[i].e; 45 if (y == fa)continue; 46 if (mxd[y] == mxd[1]) { 47 dfs1(y, x); 48 sum = (sum + dp[y]) % mod; 49 } 50 } 51 if (son[x] == 0) 52 dp[x] = 1; 53 else { 54 ll p = sum * qpow(son[x], mod - 2, mod) % mod; 55 p = (1 - p + mod) % mod; 56 dp[x] = (1 - qpow(p, son[x], mod) + mod) % mod; 57 } 58 } 59 int main() { 60 int n; 61 scanf("%d", &n); 62 init(); 63 for (int i = 1; i < n; i++) { 64 int x, y; 65 scanf("%d%d", &x, &y); 66 add(x, y), add(y, x); 67 } 68 dfs(1, 0); 69 dfs1(1, 0); 70 printf("%lld\n", dp[1]); 71 }