[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 }

猜你喜欢

转载自www.cnblogs.com/sainsist/p/11489858.html