洛谷P3978 [TJOI2015]概率论

传送门

 

rqy太强啦

数学太差限制了我的想象力……我连卡特兰数是什么都不知道……姿势不够……

令$f_i$表示有$i$个节点的二叉树的总个数,$g_i$表示$i$个节点的所有二叉树的叶子总数,那么答案就是$\frac{g_n}{f_n}$

不难发现$f_n$的递推式如下$$f_n=\sum_{i=1}^{i-n-1}f_if_{n-i-1}$$

就是枚举左子树里有几个点,那么右子树的点的个数就是总点数减去根减去左子树

然后~~百度了一下~~发现这个东西就是卡特兰数,而卡特兰数的通项公式为$$f_n=C_{2n}^n$$

于是就可以快速计算$f_n$了。现在考虑怎么计算$g_n$

~~看了rqy的表后~~不难发现$g_n=n\times f_{n-1}$。考虑如何证明

设一棵树有$n$个节点,其中有$k$个叶节点,那么去掉每一个节点都能得到一棵$n-1$个节点的树,总共能得到$k$棵

然后考虑对于每一个$n-1$个节点的树,有$n$个位置可以挂叶子(每个节点提供两个挂叶子的位置,有$n-2$地方已经被占了,剩下的就只有$n$个位置了)。于是每一棵$n-1$个节点的树会被得到$n$次。而每一种得到的方法都对应一个叶子。所以叶子结点总数为$f_{n-1}*n$

那么答案就是$$ans=\frac{g_n}{f_n}=\frac{n*f_{n-1}}{f_n}$$

把卡特兰数的通项公式带进去,化简之后得到$$ans=\frac{n*(n+1)}{2*(2n-1)}$$

不得不说这题真的太妙了

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

 

posted @ 2018-10-18 18:38  bztMinamoto  阅读(237)  评论(0编辑  收藏  举报
Live2D