洛谷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 }
深深地明白自己的弱小