洛谷P3978 [TJOI2015] 概率论 题解
题目链接:P3978 [TJOI2015] 概率论
题意:
为了提高智商,ZJY 开始学习概率论。有一天,她想到了这样一个问题:对于一棵随机生成的 $n$ 个结点的有根二叉树(所有互相不同构的形态等概率出现),它的叶子节点数的期望是多少呢?
判断两棵树是否同构的伪代码如下:
输入格式:
输入一个正整数 $n$,表示有根树的结点数。
输出格式:
输出这棵树期望的叶子节点数,要求误差小于 $10^{-9}$。
数据范围:
对于 $100\%$ 的数据,$1 \le n \le 10^9$。
设 $f_n$ 为 $n$ 个点的本质不同的二叉树的个数,$g_n$ 为这些树的叶子节点数的期望。
这个 $f_n$ 很简单,就是卡特兰数,有 $f_n = \frac{1}{n+1}\binom{2n}{n}$ 。我们考察 $g_n$ 与 $f_n$ 的关系。
打表可知 $g_n = nf_{n-1}$ 。其实证明也不难。
对于每棵 $n$ 个点的二叉树,设它有 $k$ 个叶节点
我们分别把这 $k$ 个叶子删去,会得到 $k$ 棵 $n-1$ 个点的二叉树;
而每棵 $n-1$ 个点的二叉树恰好有 $n$ 个位置可以悬挂一个新的叶子,
那么每棵 $n-1$ 个点的二叉树被得到了 $n$ 次,即 $g_n = nf_{n-1}$ 。
于是 $g_n = \frac{n(n+1)}{2(2 n-1)}$ ,这道题就做完了
时间复杂度 $\mathcal{O}(1)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)())
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
int n; cin >> n; cout << fixed << setprecision(12);
cout << 1.0 * n * (n + 1) / (2 * (2 * n - 1)) << '\n';
return 0;
}
参考文献: