zoukankan      html  css  js  c++  java
  • 【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();
    }
    
  • 相关阅读:
    Kosaraju算法---强联通分量
    Java和C++的区别
    嵌入式面试题汇总
    tabbar 之 基本结构搭建
    路由 之 再识
    常见问题 之 vue项目中使用less报错
    路由 之 初识
    VueCLI3创建项目和目录结构与配置信息详解
    runtime-compiler 和 runtime-only的区别
    vueCLI2 之 目录结构
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9203430.html
Copyright © 2011-2022 走看看