【LOJ】#2105. 「TJOI2015」概率论

题解

可以说是什么找规律好题了
但是要推生成函数,非常神奇……

任何的一切都可以用(n^2)dp说起

我们所求即是 所有树的叶子总数/所有树的方案数
我们可以列出一个递推式,设(g(x))(x)个节点构成的树的总数

那么有
(g(n) = sum_{i = 0}^{n - 1}g(i) * g(n - 1 - i))
很好理解,就是枚举左右子树的节点个数,拼出一个根节点
特殊是(g(0) = 1)

(f(x))(x)个节点构成的树的叶子总数
(f(n) = 2sum_{i = 0}^{n - 1}f(i) * g(n - 1 - i))
就是用i个节点当左子树或者右子树,乘上另一子树的方案数,就是叶子被计入的次数
特殊的是(f(1) = 1)

哎?可是复杂度是(n^2)?怎么办?

我们用生成函数!
(f(x) = sum_{i = 0}^{+infty}f(i)x^{i})
(g(x) = sum_{i = 0}^{+infty}g(i)x^{i})
有什么用啊?难道可以分治FFT?
数据范围1e9啊……gg

由于(g(x))(f(x))的递推都是卷积形式,我们尝试用卷积表示两个函数,可以得到两个方程

(g(x) = g^{2}(x) + 1)
(f(x) = 2f(x)g(x) + x)
后面的小尾巴是怎么来的?注意看我上面说的特殊点(g(0) = 1)(f(1) = 1)

运用初中数学的一元二次方程解法,我们可以得到

(g(x) = frac{1 - sqrt{1 - 4x}}{2x})(为什么只取一个符号,等会看下面写的)
(f(x) = frac{x}{sqrt{1-4x}})

解出来之后,发现这个东西十分的不优美,我们是生成函数哎??为什么没有一个整数指数幂呢?我们需要的是对应指数幂前的系数啊

然后怎么办啊?

暴力泰勒展开

我们先求一下(f(x))(g(x))的关系吧

根据敏锐的直觉我们发现
(f(x))(g(x))一定是有关系的!

而且更神奇的是…………………………
………………………………………………
………………………………………………
(int frac{f(x)}{x}dx = -frac{1}{2}sqrt{1 - 4x} + C= xg(x))
啥啥啥?我刚上幼儿园还不会导数不会积分呐qwqqqqq

你需要一本高中数学选修2-2!

我们知道微积分基本定理是,如果对于
(f(x) = F'(x))
那么(int f(x) dx = F(x) + C)
很好理解,就是,对于积分的变化率就是原来的函数嘛

同时,(frac{f(x)}{x} = frac{1}{sqrt{1-4x}})
我们需要找到一个函数的导数,正好是这个数(frac{1}{1-4x})

也就是(F'(x) = frac{1}{1-4x})

怎么找呢,先愉快换一波元
(t = 1 - 4x)
(F'(x) = frac{1}{sqrt{t}})
噫,好!这个我会
(F(x) = 2 t^{frac{1}{2}})
……

所以这个(F(x))里的(x)
把t换回去??are you sure?

我们好好看看高中选修2-2
明确讲述了,如何求一个(f(g(x)))的导数
首先设(u = g(x),y = f(x))
那么(f(g(x)) = frac{Delta y}{Delta x} = frac{Delta y}{Delta u} cdot frac{Delta u}{Delta x})
那么就很明确了(f(g(x)) = g'(x)f'(g(x)))

现在的话,我们重新求一遍
发现(F'(x) = -frac{1}{2} cdot (-4) cdot frac{1}{2} t^{-frac{1}{2}})
那么(F(x) = -frac{1}{2} t^{frac{1}{2}} + C)(C是常数,可以是任意大小)
哎?这个东西有点像……
(xg(x) = frac{1 - sqrt{1-4x}}{2} = -frac{sqrt{1-4x}}{2} + frac{1}{2})
妙啊

那么我们会发现,积分的导数就是原来的函数……即……
(frac{mathrm{d} }{mathrm{d} x} xg(x) = sum_{i = 0}^{+infty} (i + 1) g(i)x^{i} = frac{f(x)}{x})
那么(f(x) = sum_{i = 0}^{infty} (i + 1)g(i)x^{i + 1})
(f(n) = n g(n - 1))

好了,现在我们要求的东西就剩下(g(x))

让我们来暴力优雅的泰勒展开

(h(x) = xg(x) = frac{1 - sqrt{1 - 4x}}{2})
我们求一个(sqrt{1 + y})的导数
(h^{(1)}(y) = frac{1}{2} (1 + y)^{-frac{1}{2}})
(h^{(2)}(y) = frac{1}{2} (frac{1}{2} - 1) (1 + y)^{-frac{3}{2}})
(h^{(k)}(y) = prod_{i = 0}^{k - 1}(frac{1}{2} - i) (1 + y)^{frac{1}{2} - k})
然后在(y = 0)处展开
(sqrt{1 - 4x} = sum_{i = 0}^{+infty} frac{prod_{k = 0}^{i - 1} (frac{1}{2} - k)}{k!} (-4x)^{k})
我们发现这些东西的系数都是负的,但是方案数是正整数,这就是为什么这个东西选择前面是负号而不是正号

(egin{bmatrix} frac{1}{2}\ k end{bmatrix} = frac{prod_{i = 0}^{k - 1} (frac{1}{2} - i)}{k!})

那么
(h(x) = frac{1 - (1 + sum_{k = 1}^{+infty} egin{bmatrix}frac{1}{2}\k end{bmatrix} (-4x)^{k} )}{2})

我们除掉一个x
(g(x) = frac{-sum_{k = 1}^{+infty} egin{bmatrix}frac{1}{2}\k end{bmatrix} (-4)^{k}x^{k - 1}}{2})
我们对于第(k)项求一下系数
(A_k = -frac{prod_{i = 0}^{k} (frac{1}{2} - i) (-4)^{k + 1}}{2(k + 1)!})
(A_k = frac{(-1)^{k + 2} 2^{2k + 1} prod_{i = 0}^{k} (frac{1}{2} - i)}{(k + 1)!})
我们把-1的指数减掉2,分配给每个乘积里的数,然后把2分配进乘积里
(A_k = frac{2^{k} prod_{i = 1}^{k} (2i - 1)}{(k + 1)!})
(A_k = frac{prod_{i = 1}^{k}(2i - 1) prod_{i = 1}^{k}2i}{k!(k + 1)!})
(A_k = frac{1}{k + 1} inom{2k}{k})
(inom{2k}{k})就是我们很熟悉的卡特兰数了
这样的话
我们只要
固输(frac{n(n + 1)}{2(2n - 1)})就可以得满分了。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <bitset>
#include <queue>
#define enter putchar('
')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define MAXN 100005
#define eps 1e-12
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 - '0' + c;
	c = getchar();
    }
    res = res * f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
db N;
void Solve() {
    scanf("%lf",&N);
    N = N * (N + 1) / (2 * (2 * N - 1));
    printf("%.9lf",N);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}
原文地址:https://www.cnblogs.com/ivorysi/p/9203430.html