【BZOJ4001】概率论(TJOI2015)-生成函数+卡特兰数+微积分

本文探讨了如何利用生成函数和卡特兰数解决概率论中关于二叉树的叶子节点计数问题,并给出了简洁的数学推导及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试地址:概率论
做法:本题需要用到生成函数+卡特兰数+微积分。
g(i) g ( i ) i i 个节点的不同构的二叉树数目,我们知道这就是卡特兰数。再令f(i) i i 个节点的所有不同构的二叉树的叶子节点数总和。答案显然就是f(n)g(n)
首先很快得出 f f 的递推式:
f(1)=1,f(n(n2))=2i=0n1f(i)g(ni1)
G,F G , F 分别为 g,f g , f 的生成函数,根据 g g 的递推式:
g(0)=1,g(n(n1))=i=0n1g(i)g(ni1)
发现很是一个卷积的形式,但是右边算的卷积会被放在 n1 n − 1 的位置上,要使它放在 n n 的位置上需要往右移一位,在生成函数上的体现就是乘个x。别忘了补一个 1 1 来表示g(0)。于是有:
G(x)=x[G(x)]2+1 G ( x ) = x [ G ( x ) ] 2 + 1
解一元二次方程得: G(x)=114x2x G ( x ) = 1 − 1 − 4 x 2 x (分子那个 为什么不能取+尚不了解,但往下算到某一步能看出 + + 不行)。
我们用相似的方式分析f的递推式,有:
F(x)=2xF(x)G(x)+x F ( x ) = 2 x F ( x ) G ( x ) + x
将前面求出的 G(x) G ( x ) 代入计算,得到:
F(x)=x14x F ( x ) = x 1 − 4 x
有了 F(x) F ( x ) 的表达式,但是怎么把它写成级数展开的形式呢?直接泰勒展开?太麻烦了。我们注意到:
14x 1 − 4 x 的导数是 214x − 2 1 − 4 x (用链式法则计算)。
也就是说:
F(x)xdx=1214x+C=xG(x) ∫ F ( x ) x d x = − 1 2 1 − 4 x + C = x G ( x ) (当 C=12 C = 1 2 时)
于是我们有:
F(x)=x[xG(x)] F ( x ) = x [ x G ( x ) ] ′ (x) ( x ) ′ 表示 x x 的导函数)
这就变成了对生成函数乘x和求导的问题。乘 x x 就相当于数列向后移位,那么求导是什么呢?因为生成函数是一个多项式,因此可以每一项分开求导。因此我们有:
G(x)=i=0g(i)xi
xG(x)=i=0g(i)xi+1 x G ( x ) = ∑ i = 0 ∞ g ( i ) x i + 1
[xG(x)]=i=0(i+1)g(i)xi [ x G ( x ) ] ′ = ∑ i = 0 ∞ ( i + 1 ) g ( i ) x i
x[xG(x)]=i=0(i+1)g(i)xi+1=F(x) x [ x G ( x ) ] ′ = ∑ i = 0 ∞ ( i + 1 ) g ( i ) x i + 1 = F ( x )
因此 f(n)=ng(n1) f ( n ) = n ⋅ g ( n − 1 ) ,所以 f(n)g(n)=ng(n1)g(n) f ( n ) g ( n ) = n ⋅ g ( n − 1 ) g ( n )
有因为我们知道 g g 是卡特兰数,所以g(n)=1n+1C2nn,那么把组合数拆开化简得:
ng(n1)g(n)=n(n+1)2(2n1) n ⋅ g ( n − 1 ) g ( n ) = n ( n + 1 ) 2 ( 2 n − 1 )
于是寥寥几行代码就解决了这个问题(这真的不是在考数学么……)。
(当然你要是打表找规律或者硬是通过组合意义得出这个式子我也没有意见……)
以下是本人代码:

#include <bits/stdc++.h>
using namespace std;
double n;

int main()
{
    scanf("%lf",&n);
    printf("%.9lf",n*(n+1.0)/(2.0*(2.0*n-1.0)));

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值