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

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

#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;
}
posted @ 2018-07-07 19:24  Maxwei_wzj  阅读(339)  评论(0编辑  收藏  举报