zoukankan      html  css  js  c++  java
  • 普通型生成函数总结

    普通型生成函数

    什么是生成函数?

    生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。最早提出母函数的人是法国数学家(Laplace)(P.S.)在其1812年出版的《概率的分析理论》中明确提出)。 生成函数有普通型生成函数和指数型生成函数两种,其中普通型用的比较多。 生成函数的应用简单来说在于研究未知(通项)数列规律,用这种方法在给出递推式的情况下求出数列的通项,生成函数是推导(Fibonacci)数列的通项公式方法之一。 另外生成函数也广泛应用于编程与算法设计、分析上,运用这种数学方法往往对程序效率与速度有很大改进。

    ——百度百科

    黑人问号.jpg

    简单来说,给你一个数列(a),如果多项式(f(x))(i)次项系数(k_i=a_i)(这里根据需要可能是(a_{i+1})),那么称(f(x))(a)的生成函数。

    有什么用?

    是的,这玩意儿乍一看感觉就是换了一种方式表示一个数列,并没有什么实际作用。但是......我们还是通过一个例子来了解它的强大之处吧。

    神犇(Monster\_Qi)(yyg)热衷于切大火题,假设(Monster\_Qi)一天最多切(4)道大火题,(yyg)一天最多切(3)道大火题,那么有多少种情况,他们一天一共切了(5)道大火题,两种情况被认为是不同的当且仅当两人中存在一人做题数目不同。

    我们可以用两个数列分别表示一天内两人各自做题数量的所有可能情况:

            id: 0 1 2 3 4 5 6 ...
    Monster_Qi: 1 1 1 1 1 0 0 ...
           yyg: 1 1 1 1 0 0 0 ...
    

    这两个数列的意义是:当一个数列的第(i)项为(1)时,表示这个数列对应的人一天做了(i)道题的情况有(1)种。

    显然两个数列的生成函数分别为:

    [f(x)=1+x+x^2+x^3+x^4 ]

    [g(x)=1+x+x^2+x^3 ]

    考虑手算答案数列:

     id: 0 1 2 3 4 5 6 7 8 9 10 ...
    ans: 1 2 3 4 4 3 2 1 0 0 0  ...
    

    答案数列的意义是:两个人一天做了(i)道题的情况有(ans_i)种。

    (ans)的生成函数就是......

    [h(x)=1+2x+3x^2+4x^3+4x^4+3x^5+2x^6+x^7 ]

    等等!我们发现:

    [h(x)=f(x) imes g(x) ]

    因吹斯婷,我们成功把组合问题转化为了多项式相关的问题。

    我们在使用生成函数时,一般会根据等比数列求和公式,把(f(x),g(x))化为:

    [f(x)=frac{1-x^5}{1-x} ]

    [g(x)=frac{1-x^4}{1-x} ]

    继续刚才(Monster\_Qi)(yyg)的切题之旅。

    但是(Monster\_Qi)那么强,怎么可能一天只做(4)道题?(Monster\_Qi)一天内最多可以做无限道题,但是他实在是太(6)了,所以他希望他一天做题的数量是(6)的倍数((0)被认为是(6)的倍数)。

    容易得到生成函数:

    [f(x)=1+x^6+x^{12}+x^{18}+x^{24}+... ]

    这个(f(x))有无穷项,很难处理。

    但是根据等比数列求和公式,当(0<x<1)时,有:

    [f(x)=frac{1}{1-x^6} ]

    而在使用生成函数时,(x)的取值无实际意义,所以我们可以认为上式成立。

    以上介绍的便是普通型生成函数,普通型生成函数可以用于解决多重集的组合问题,其将组合个数转化为了多项式对应次项的系数,从而可以使用等比数列求和公式甚至多项式相关算法进行快速计算。此外,生成函数还包含指数型生成函数等。由于博主目前实力有限,还不能给大家带来关于其他生成函数的介绍,在此深表歉意。

    一些例题?

    [BZOJ3027][Ceoi2004]Sweet

    Description

    (John)得到了(n)罐糖果。不同的糖果罐,糖果的种类不同(即同一个糖果罐里的糖果种类是相同的,不同的糖果罐里的糖果的种类是不同的)。第(i)个糖果罐里有(m_i)个糖果。(John)决定吃掉一些糖果,他想吃掉至少(a)个糖果,但不超过(b)个。问题是(John)无法确定吃多少个糖果和每种糖果各吃几个。有多少种方法可以做这件事呢?

    Input

    从标准输入读入每罐糖果的数量,整数(a)(b)
    (John)能够选择的吃掉糖果的方法数(满足以上条件)。

    Output

    把结果输出到标准输出(把答案模(2004)输出)。
    (1 leq N leq 10,0 leq a leq b leq 10^7,0 leq Mi leq 10^6)

    Sample Input
    2 1 3
    3
    5
    
    Sample Output
    9
    
    Hint

    ((1,0),(2,0),(3,0),(0,1),(0,2),(0,3),(1,1),(1,2),(2,1))

    题解

    题目要求我们吃掉([a,b])个糖果,我们可以将其转化为前缀和相减的形式,即我们现在要求的是至多吃(k)个糖果的方案数。

    在第(i)个糖果罐中,我们可以吃掉(0,1,2,3,...,m_i)个糖果。所以对于第(i)个糖果罐,我们有生成函数:

    [f_i(x)=1+x+x^2+x^3+...+x^{m_i} ]

    根据我们之前的叙述,将所有的(f_i(x))乘起来得到的多项式(F(x))(0 sim k)次项系数的和便是我们想要的答案。

    [egin{align} F(x)&=prod_{i=1}^{n}f_i(x)\ &=prod_{i=1}^{n}(1+x+x^2+x^3+...+x^{m_i})\ &=prod_{i=1}^{n}frac{1-x^{m_i}}{1-x}\ &=frac{prod_{i=1}^{n}(1-x^{m_i+1})}{(1-x)^n}\ &=(1+x+x^2+x^3+...)^nprod_{i=1}^{n}(1-x^{m_i+1})\ end{align} ]

    对于后面一部分(prod_{i=1}^{n}(1-x^{m_i+1})),由于(n)很小,可以通过(O(2^n))爆搜展开。假设我们爆搜出了一项(px^q),那么前面一部分((1+x+x^2+x^3+...)^n)展开后次数(leq k-q)的项的系数之和( imes p)可以对答案产生贡献。

    如何求(0 sim k-q)次项的系数和?

    根据广义二项式定理(不好意思,这个我不会)或是隔板法分析,可以发现,((1+x+x^2+x^3+...)^n)展开后(i)次项系数为(C_{n+i-1}^{n-1})

    根据组合数的性质,有:

    [sum_{i=0}^{k-q}C_{n+i-1}^{n-1}=C_{n+k-q}^{n} ]

    本题终结。

    [BZOJ3028]食物

    Description

    明明这次又要出去旅游了,和上次不同的是,他这次要去宇宙探险!我们暂且不讨论他有多么(NC),他又幻想了他应该带一些什么东西。理所当然的,你当然要帮他计算携带(N)件物品的方案数。他这次又准备带一些受欢迎的食物,如:蜜桃多啦,鸡块啦,承德汉堡等等当然,他又有一些稀奇古怪的限制:每种食物的限制如下:

    承德汉堡:偶数个。

    可乐:(0)个或(1)个。

    鸡腿:(0)个,(1)个或(2)个。

    蜜桃多:奇数个。

    鸡块:(4)的倍数个。

    包子:(0)个,(1)个,(2)个或(3)个。

    土豆片炒肉:不超过一个。

    面包:(3)的倍数个。

    注意,这里我们懒得考虑明明对于带的食物该怎么搭配着吃,也认为每种食物都是以‘个’为单位(反正是幻想嘛),只要总数加起来是(N)就算一种方案。因此,对于给出的(N),你需要计算出方案数,并对(10007)取模。

    (N leq 10^{500})

    题解

    这个数据范围逗我呢?!

    先分析题意,容易写出各种食物的生成函数,这里博主不给出具体过程,直接给出所有生成函数的积为(frac{x}{(1-x)^4})

    类似上题插板法的分析过程,容易得到答案为(C_{n+2}^{3})

    本题终结。

    (FFT)?好东西

    [BZOJ3771]Triple

    题面太长不粘。

    题解

    (A,B,C)分别表示同一把斧头取一,二,三次的生成函数,即对于每一个(a_i)

    A[a[i]]+=1;
    B[a[i]*2]+=1;
    C[a[i]*3]+=1;
    

    根据容斥原理,答案的生成函数为:

    [A+(A*A-B)/2+(A*A*A-3*A*B+2*C)/6 ]

    (这里可以认为是先求排列数,再通过除以阶乘转化为组合数。)

    使用(FFT)快速计算多项式乘法即可。

    斐波那契数列的生成函数

    [f(x)=frac{1}{1-x-x^2} ]

    参考博客

    https://www.cnblogs.com/RabbitHu/p/9178645.html

    https://blog.csdn.net/wu_tongtong/article/details/78854572

    特别鸣谢

    (Monster\_Qi)

    (yyg)

  • 相关阅读:
    pexpect库学习之包装类详解
    spawn类expect方法详解
    spawn类参数command详解
    Django中如何实现数据库路由?
    Memcached中的存取命令详解
    Javascript的参数详解
    Python中Paramiko协程方式详解
    Greenlets间如何实现互相通信?
    Gevent中的同步与异步详解
    jQuery正则的使用方法步骤详解
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10010044.html
Copyright © 2011-2022 走看看