P3978 [TJOI2015]概率论
题目描述
Solution
设CnC_nCn表示nnn个节点的树的个数(卡特兰数),SnS_nSn表示nnn个节点的所有树的叶子的个数和。
Cn=∑i=0n−1CiCn−i−1+[n==0]Sn=2∑i=0n−1SiCn−i−1+[n==1]C_n=\sum_{i=0}^{n-1} C_iC_{n-i-1}+[n==0]\\ S_n=2\sum_{i=0}^{n-1} S_iC_{n-i-1}+[n==1] Cn=i=0∑n−1CiCn−i−1+[n==0]Sn=2i=0∑n−1SiCn−i−1+[n==1]
写出CnC_nCn和SnS_nSn的生成函数:
C(z)=z∑n,iCiziCn−i−1zn−i−1S(z)=2z∑n,iSiziCn−i−1zn−i−1+zC(z)=z\sum_{n,i}^{}C_iz^iC_{n-i-1}z^{n-i-1}\\ S(z)=2z\sum_{n,i}^{}S_iz^iC_{n-i-1}z^{n-i-1}+z C(z)=zn,i∑CiziCn−i−1zn−i−1S(z)=2zn,i∑SiziCn−i−1zn−i−1+z
因此:
C(z)=zC(z)C(z)+1S(z)=2zS(z)C(z)+zC(z)=zC(z)C(z)+1\\ S(z)=2zS(z)C(z)+z C(z)=zC(z)C(z)+1S(z)=2zS(z)C(z)+z
将C(z)C(z)C(z)当做一个未知数,解出一元二次方程的解C(z)C(z)C(z):
C(z)=1−1−4z2zC(z)=\frac{1-\sqrt{1-4z}}{2z}\\ C(z)=2z1−1−4z
继续推出S(z)S(z)S(z)的表达式:
(1−2zC(z))S(z)=zS(z)=z1−2zC(z)S(z)=z1−2z1−1−4z2zS(z)=z1−4z(1-2zC(z))S(z)=z\\ S(z)=\frac{z}{1-2zC(z)}\\ S(z)=\frac{z}{1-2z\frac{1-\sqrt{1-4z}}{2z}}\\ S(z)=\frac{z}{\sqrt{1-4z}} (1−2zC(z))S(z)=zS(z)=1−2zC(z)zS(z)=1−2z2z1−1−4zzS(z)=1−4zz
因此我们想要知道的就是[zn]S(z)[z^n]S(z)[zn]S(z),也就是S(z)S(z)S(z)在znz^nzn的系数。
有:
S(z)=z(1−4z)−12S(z)=z∑n>=0(−12n)(−4z)nS(z)=∑n>=1(−12n−1)(−4)n−1znS(z)=z(1-4z)^{-\frac{1}{2}}\\ S(z)=z\sum_{n>=0}\tbinom{-\frac{1}{2}}{n}(-4z)^n\\ S(z)=\sum_{n>=1}\tbinom{-\frac{1}{2}}{n-1}(-4)^{n-1}z^n S(z)=z(1−4z)−21S(z)=zn>=0∑(n−21)(−4z)nS(z)=n>=1∑(n−1−21)(−4)n−1zn
其中
∑n>=0(−12n)(−4)n=(2nn)\sum_{n>=0}\tbinom{-\frac{1}{2}}{n}(-4)^{n}=\tbinom{2n}{n} n>=0∑(n−21)(−4)n=(n2n)
因此
S(z)=(2n−2n−1)znS(z)=\tbinom{2n-2}{n-1}z^n\\ S(z)=(n−12n−2)zn
[zn]S(z)=(2n−2n−1)[z^n]S(z)=\tbinom{2n-2}{n-1} [zn]S(z)=(n−12n−2)
答案就是
Ans=(2n−2n−1)Cn=(2n−2n−1)(n+1)(2nn)=n(n+1)2(2n−1)Ans =\frac{\tbinom{2n-2}{n-1}}{C_n} =\frac{\tbinom{2n-2}{n-1}(n+1)}{\tbinom{2n}{n}}=\frac{n(n+1)}{2(2n-1)} Ans=Cn(n−12n−2)=(n2n)(n−12n−2)(n+1)=2(2n−1)n(n+1)
时间复杂度O(你想咋地就咋地)O(你想咋地就咋地)O(你想咋地就咋地),可能会有点卡精度。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=10007;
const int inv6=(mods+1)/6;
const int MAXN=600005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=((x<<3)+(x<<1)+(c^48))%mods; c=getchar(); }return x*f;
}
int main()
{lod n;scanf("%Lf",&n);printf("%.12Lf\n",n/(n*2-1)*(n+1)/2);return 0;
}