1. 程式人生 > >洛谷 P3830 [SHOI2012]隨機樹

洛谷 P3830 [SHOI2012]隨機樹

view 不出 lap cal %d def www. ide img

https://www.luogu.org/problemnew/show/P3830

具體方法見代碼。。

其實挺神奇的,概率可以先算出“前綴和”(A小於等於xxx的概率),然後再“差分”得到A恰好為xxx的概率

話說推了很久“x個葉子節點的樹,左子樹有y個節點”的概率的dp,推不出來,然後無意間手玩了一下5個葉子節點,發現這個東西其實就等於1/(x-1),跟y沒有關系。。。

技術分享圖片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4
#include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 typedef long double ldb; 14 int q,n; 15 /* 16 int calc(int x,int y)//x個葉節點的樹,左子樹y個葉節點的概率
17 { 18 return ldb(1)/(x-1); 19 } 20 */ 21 ldb an[110][110]; 22 //an[i][j]表示i個葉節點的樹,所有節點深度<=j的概率 23 bool v1[110][110]; 24 ldb ans; 25 ldb dfs(int x,int y) 26 { 27 if(x==1) return 1; 28 if(y==0) return 0; 29 if(v1[x][y]) return an[x][y]; 30 ldb ans=0;int i; 31 for
(i=1;i<x;i++) 32 //ans+=calc(x,i)*dfs( 33 ans+=dfs(i,y-1)*dfs(x-i,y-1); 34 v1[x][y]=1; 35 return an[x][y]=ans/(x-1); 36 } 37 int main() 38 { 39 int i;ldb t; 40 scanf("%d%d",&q,&n); 41 if(q==1) 42 { 43 t=0; 44 for(i=2;i<=n;i++) 45 { 46 t+=2.0/i; 47 } 48 printf("%.6Lf",t); 49 } 50 else 51 { 52 for(i=1;i<n;i++) 53 { 54 ans+=i*(dfs(n,i)-dfs(n,i-1)); 55 } 56 printf("%.6Lf",ans); 57 } 58 return 0; 59 }
View Code

洛谷 P3830 [SHOI2012]隨機樹