• [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 }

     Tips:bzoj貌似没有spj,所以在bzoj上提交一定要输出九位小数......

  • 相关阅读:
    C# 控制台程序如何输出Messagebox
    C# VS如何整个项目中查找字符串
    C# .NET using ManagementObjectSearcher提示缺少引用怎么办
    [React] Write a Custom State Hook in React
    [GCP] Goolge compute Engine
    [Kubernetes] Defining a Pod with YAML
    [Kubernetes] Kubectl and Pod
    [Schematics] 1. Copy and Manipulate Template
    [Schematics] 0. Schematics "Hello World"
    [RxJS] Subject asObservable() method
  • 原文地址:https://www.cnblogs.com/cervusy/p/9746975.html
Copyright © 2020-2023  润新知