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 }