[TJOI2015]概率论
题目描述
为了提高智商,ZJY开始学习概率论。有一天,她想到了这样一个问题:对于一棵随机生成的n个结点的有根二叉树(所有互相不同构的形态等概率出现),它的叶子节点数的期望是多少呢?
判断两棵树是否同构的伪代码如下:
输入输出格式
输入格式:
输入一个正整数n,表示有根树的结点数
输出格式:
输出这棵树期望的叶子节点数,要求误差小于1e-9
输入输出样例
说明
数据范围
对于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; }