【2019icpc徐州站】Random Access Iterator(概率dp,有坑,tricks)
題干:
Recently Kumiko learns to use containers in C++ standard template library.
She likes to use the?std::vector?very much. It is very convenient for her to do operations like an ordinary array. However, she is concerned about the random-access iterator use in the?std::vector. She misunderstanding its meaning as that a vector will return an element with equal probability in this container when she access some element in it.
As a result, she failed to solve the following problem. Can you help her?
You are given a tree consisting of?nn?vertices, and?11?is the root of this tree. You are asked to calculate the height of it.
The height of a tree is defined as the maximum number of vertices on a path from the root to a leaf.
Kumiko's code is like the following pseudo code.
She calls this function?dfs(1, 1), and outputs the maximum value of depth array.
Obviously, her answer is not necessarily correct. Now, she hopes you analyze the result of her code.
Specifically, you need to tell Kumiko the probability that her code outputs the correct result.
To avoid precision problem, you need to output the answer modulo?10^9 + 7109+7.
Input
The first line contains an integer?nn?- the number of vertices in the tree?(2 \le n \le 10^6)(2≤n≤106).
Each of the next?n - 1n?1?lines describes an edge of the tree. Edge?ii?is denoted by two integers?u_iui??and?v_ivi?, the indices of vertices it connects?(1 \le u_i, v_i \le n, u_i \cancel= v_i)(1≤ui?,vi?≤n,ui?=?vi?).
It is guaranteed that the given edges form a tree.
Output
Print one integer denotes the answer.
樣例輸入復制
5 1 2 1 3 3 4 3 5樣例輸出復制
750000006樣例解釋
Kumiko's code has?\frac{3}{4}43??probability to output the correct answer.
題目大意:
給定一棵樹,1號節點為根節點,定義了一下一棵樹的深度。定義一個過程:從根節點出發,在節點x有son[x]次重復操作(son[x]為x節點的兒子節點個數),每次操作等概率進入某一兒子節點,同時記錄最深深度dep。
現在調用一次dfs(1),求? ?dep==樹的深度? 的概率。
解題報告:
就是個n次獨立重復試驗,每一次的概率算出來,求個son[x]次方就行了。
注意判斷葉子結點的時候別忘了特判根節點。、。。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 1e6 + 5; const ll mod = 1e9 + 7; ll qpow(ll a,ll b) {ll res = 1;while(b) {if(b&1) res = (res * a) % mod;b>>=1;a = (a*a)%mod;}return res; } int n,dep[MAX],ansd; ll dp[MAX]; vector<int> vv[MAX]; void dfs(int cur,int fa,int deep) {dep[cur] = deep;ansd = max(ansd,deep);int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == fa) continue;dfs(v,cur,deep+1);} } void f(int cur,int fa) {if(vv[cur].size() == 1 && cur != 1) {if(dep[cur] == ansd) dp[cur] = 1;else dp[cur] = 0;return;}int up = vv[cur].size(),upp = vv[cur].size() - (cur!=1);ll tmp = 0; for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == fa) continue;f(v,cur);tmp += dp[v] *(qpow(upp,mod-2))%mod;tmp%=mod;}tmp = mod + 1 - tmp;//一次錯誤的tmp%=mod;tmp = qpow(tmp,upp)%mod; dp[cur] = mod+1-tmp;dp[cur]%=mod; } int main() {cin>>n;if(n == 1) {printf("1\n");return 0;}for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);vv[v].pb(u);vv[u].pb(v);}dfs(1,0,1);f(1,0);printf("%lld\n",dp[1]);return 0 ; }?
總結
以上是生活随笔為你收集整理的【2019icpc徐州站】Random Access Iterator(概率dp,有坑,tricks)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IE浏览器退役后:Edge兼容模式标签页
- 下一篇: wingate.exe - wingat