[TJOI2015]概率论

题目描述

为了提高智商,ZJY开始学习概率论。有一天,她想到了这样一个问题:对于一棵随机生成的n个结点的有根二叉树(所有互相不同构的形态等概率出现),它的叶子节点数的期望是多少呢?

判断两棵树是否同构的伪代码如下:

输入输出格式

输入格式:

 

输入一个正整数n,表示有根树的结点数

 

输出格式:

 

输出这棵树期望的叶子节点数,要求误差小于1e-9

 

输入输出样例

输入样例#1: 
1
输出样例#1: 
1.000000000
输入样例#2: 
3
输出样例#2: 
1.200000000

说明

数据范围

对于30%的数据,1 ≤ n ≤ 10

对于70%的数据,1 ≤ n ≤ 100

对于100%的数据,1 ≤ n ≤ 10^9

 

     这可能是我见过思维含量和代码长度的比值最大的一道题了2333.

    首先有多项式恐惧症的人就不要往下看了2333,底下全是式子。

    首先设g[x] 为 节点数是 x 的二叉树有多少种,显然枚举根的左右子树可以得到: g[x] = Σ g[i] * g[x-i-1] 。特殊的,这里g[0]=1,表示空子树。

可以发现这是一个卡特兰数的表示,所以直接得到通项: g[x] = (2x)!/(x!*x!*(x+1))。

    我们还可以设 多项式A = Σx^i * g[i] ,那么显然 A=x*A^2 + 1,我们解一下多项式之后发现它的闭形式为 (1-sqrt(1-4x))/2x。另一个根因为不收敛所以被舍去了。

 

    再设 f[i] 为i节点数为i的二叉树的叶子数的期望(显然 f[0]=0,f[1]=1),那么 f[x] =  Σ (f[i] + f[x-i-1]) * g[i] * g[x-i-1] /g[x] =     2*Σ f[i] * g[i] * g[x-i-1] /g[x] ,所以 g[x] * f[x] = 2*Σ f[i] * g[i] * g[x-i-1],我们就再设h[i] = f[i] * g[i] (显然h[0]=0,h[1]=1),设多项式B = Σx^i * h[i] 。那么可以得到: B=x*B*A + x,然后解一下多项式可以得到 B = x * (1-4x)^(-1/2)。

     其实我们可以先求 C = (1-4x)^(-1/2) ,然后把它右移一位就是B。

     也就是我们如果相求B中n次项前的系数的话,求一下C中的第n-1项就行了。

    解C的话,我们套用一下广义二项式定理(不会的请自觉百度),可以得到 C(n) = (-1/2)*(-1/2 - 1)*(-1/2 - 2)*....*(-1/2 - n+1)/ n! *(-4)^n 。强行化简一波发现上式 = (2n)!/(n!n!) ,所以 B(n) = (2n-2)!/((n-1)!(n-1)!)。

 

      也就是 h[i] = (2i-2)!/((i-1)!(i-1)!) ,所以 f[i] = h[i]/g[i] = i*(i+1)/(4*i-2)。

 

然后就可以做到6行以内A一道较难省选题了2333

 

#include<bits/stdc++.h>
double a;
int main(){
    scanf("%lf",&a);
    printf("%.11lf\n",a*(a+1)/(2*(2*a-1)));
    return 0;
}

  

 

posted @ 2018-03-23 21:49  蒟蒻JHY  阅读(849)  评论(0编辑  收藏  举报