[TJOI2015] 概率论

洛谷 P3978 传送门

一道烧脑的黑题,但是代码只有不到10行......

先求出g(n),g(n)代表n个节点的二叉树有多少。

显然g(n)=g(1)*g(n-2)+g(2)*g(n-2)+...+g(n-1)*g(0)

即:左子树有1个节点,右子树就是n-1个节点;左子树有2个节点,右子树就是n-2个节点...以此类推。

最后的g(n-1)*g(0)是一侧子树为空的情况。

这显然是卡特兰数。这里就是卡特兰数的套路:

卡特兰数的两种来源:1.递推式 2.组合数C(2n,n)/(n+1)

在实际应用的过程中,我们经常是通过递推式发现要用到卡特兰数,最后通过组合数的方式把它求出来。

这道题也不例外。

求出了g(n),下面考虑怎么求出g(n)种n个节点的二叉树的叶子节点数的总和f(n)。

可以看出,对于一颗n个节点的二叉树,去掉一个叶子节点,就能够得到一颗n-1个节点的二叉树。

如果这个n个节点的二叉树有k个叶子节点,就能通过这样得到k颗n-1个节点的二叉树。

而把所有的n个节点的二叉树一起考虑,就得到:(所有n个节点的二叉树的叶子节点之和)=(叶子节点数的平均数K)*(n-1个节点的二叉树的总数)。

即:f(n)=K*g(n-1)。

我们还知道,每个n-1个节点的二叉树,都有n个位置可以补上一个叶子。

证明:只有1个节点的树有两个空位置。每增加一个节点,占用原来的一个位置,多出来两个位置。

所以每个n-1个节点的二叉树,都被得到了n次。

最后得到:f(n)=n*g(n-1)。

所以ans=f(n)/g(n)=[n*(n+1)] / [2*(2n-1)]。

1 #include<cstdio>
2 
3 int main()
4 {
5     double n;
6     scanf("%lf",&n);
7     printf("%.10lf",n*(n+1)/(4*n-2));
8 }

猜你喜欢

转载自www.cnblogs.com/eternhope/p/9746975.html