• 【讲稿】8.13杂题选讲 | 【学习笔记】普通生成函数 | 【题解】 luogu P2000 拯救世界


    • UPD on 8.11:纠正了关于斐波那契数列待定系数法的方程
    • UPD on 8.12:纠正了关于收敛半径的描述

    又要杂题选讲了qwq,由于本人太菜而且暑假集训后完全在搞whk啥题都没刷,于是只能讲模板了/kk

    一.啥是生成函数

    生成函数是一个晾衣绳,我们把一系列的数字挂在上面以供显示。——《(Generating) (Funtionology)

    上面那句话是什么意思,我们姑且不谈反正我也不知道是什么意思。我们从中大概可以感受到,生成函数是一种处理序列问题的工具,那么我们接下来再看这本书里的另一端话:

    假设我们有一个问题,答案是一系列的数字({ a_i }),我们想知道这个序列是什么。我们会得到什么样的答案呢?
    一个简单的公式将是最好的。如果我们发现对于每个 (n=0,1,2,…,a_n=n^2+3),那么毫无疑问我们已经“回答”了这个问题。
    但是如果没有简单的公式来计算未知序列?毕竟,有些序列是复杂的——举个令人毛骨悚然的例子,假设未知序列是({ 2,3,5,7,11,13,17,19,…,}) 其中 (a_n) 是第 (n) 个素数。那么,它指望得到任何一种简单的公式都是不合理的。
    生成函数给你提供另外一种解决这种问题的有力方式,虽然给序列成员一个简单的公式是不可能的,但是我们可以给出一个关于幂级数和的简单公式,它的系数就是我们要找的序列。——《(Generating) (Funtionology)

    好的,我们现在已经知道生成函数是用来干什么的了,接下来我们直接切入正题——

    二.普通生成函数 (opsgf) 的定义

    我们定义一个序列 ({ a_i }) 的普通生成函数为

    [F(x)=sumlimits_{k}{a_kx^k} ]

    ({ a_i }) 既可以是有穷序列,也可以是无穷序列,下面有一些常见的例子:

    1. 序列 ({1,2,3}) 的普通生成函数是 (F(x)=1+2x+3x^2)
    2. 序列 ({1,1,...,1}) 的普通生成函数是 (sumlimits_{k}{x^k})

    换句话说,如果序列 ({ a_i }) 有通项公式,那么他的生成函数的系数就应该是他的通项公式。
    知道了上面的东西并没有任何用处,我们不知道怎么应用它,而他的用法——求封闭形式,就要从我们提到过的序列 ({1,1,...,1}) 的普通生成函数

    [F(x)=sumlimits_{k}{x^k} ]

    讲起——

    三.普通生成函数的封闭形式

    大家可能在很多地方都见到过这样一个定理:

    [sumlimits_{k geq 0}{x^k}=frac{1}{1-x} ]

    这个定理的正确性看起来一点也不显然嘛,那我们换个角度看问题:
    有个非常显然的性质:

    [F(x)x+1=F(x) ]

    其实他就相当于把 (F(x)) 整体向右平移一位,然后在前面补 (1) ,其实这种方法类似扰动法的解方程,我们把上面的那个方程解了,就得到了这个定理

    [sumlimits_{k geq 0}{x^k}=frac{1}{1-x} ]

    这玩意的收敛半径是 (|x| < 1)
    如果你理解了上面的过程,那么恭喜你,你已经初步掌握了生成函数的处理技巧之一——求封闭形式。
    我们把上面的过程称为求封闭形式,把从 (frac{1}{1-x}) 推回原来的函数称为级数展开,而且显然这两个东西是可以互推的。
    好的,那么在我们初步学会了普通生成函数之后,我们来看一个应用。

    四.利用普通生成函数解斐波那契数列的通项问题

    • 问题:定义斐波那契数列 (f_i=f_{i-1}+f_{i-2},f_1=f_2=1),求 ({ f_i }) 通项。

    解:首先设 ({ f_i }) 的普通生成函数为

    [F(x)=sumlimits_{k geq 1}{f_kx^k} ]

    这个套路在《(Generating) (Funtionology)》里面被称为 (Snake) (Oil) (Method),继续按套路,设

    [G(x)=sumlimits_{k geq 3}{f_kx^k}=F(x)-x-x^2 ]

    其实这个套路跟我们上面求 (sumlimits_{k geq 0}{x^k}) 的作用是一样的,都是通过发现 (F(x)) 的性质从而解出他的封闭形式,那么有:

    [G(x)=sumlimits_{k geq 3}{f_kx^k}=sumlimits_{k geq 3}{(f_{k-1}+f_{k-2})x^k}=xsumlimits_{k geq 2}{f_kx^k}+x^2 sumlimits_{k geq 1}{f_kx^k}=x(F(x)-x)+x^2F(x) ]

    结合 (G(x)=F(x)-x-x^2),移项解得:

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

    这就是斐波那契数列的生成函数。
    到了这一步,我们将它级数展开,按套路设:

    [frac{x}{1-x-x^2}=frac{x}{(1-x·x_1)(1-x·x_2)}=frac{A}{1-x·x_1}+frac{B}{1-x·x_2} ]

    可解得 (x_1=frac{1 + sqrt 5}{2},x_2=frac{1 - sqrt 5}{2}),整理上式有:

    • (frac{x}{1-x·x_2}=A+frac{1-x·x_1}{1-x·x_2}B)
    • (frac{x}{1-x·x_1}=B+frac{1-x·x_2}{1-x·x_1}A)

    这个是一个非常经典的 (trick),推很多别的生成函数的式子的时候都可以这样子做,在这两个式子中分别令 (x·x_1=1,x·x_2=1),最后可解出:

    [A=frac{1}{sqrt 5},B=-frac{1}{sqrt 5} ]

    (F(x)=frac{A}{1-x·x_1}+frac{B}{1-x·x_2})级数展开:

    [F(x)=A(sumlimits_{k geq 1}{(x·x_1)^k})+B(sumlimits_{k geq 1}{(x·x_2)^k}) ]

    (A,B,x_1,x_2) 全部代入,最后有:

    [F(x)=sumlimits_{k geq 1}[frac{1}{sqrt 5}(frac{1 + sqrt 5}{2})^k-frac{1}{sqrt 5}(frac{1 - sqrt 5}{2})^k]x^k ]

    于是有斐波那契数列的通项公式:

    [f_n=[x^n]F(n)=frac{1}{sqrt 5}(frac{1 + sqrt 5}{2})^n-frac{1}{sqrt 5}(frac{1 - sqrt 5}{2})^n ]

    好的,看来我们现在已经成功应用普通生成函数解决了一些有趣的问题了,下面我们对上面的思想/套路作一些总结:

    1. 首先,我们要求序列 ({ a_i }) 的通项公式,那么就把它的普通生成函数 (F(x)) 设出来
    2. 求出 (F(x)) 的封闭形式
    3. 再把 (F(x)) 的封闭形式展开,取系数,就得到了答案

    好哇,这就是我们今天杂题选讲的全部内容了,大家再见!
    好吧,既然是杂题选讲,还是得讲点题的。

    五.例题:LG P2000 拯救世界

    我们将题目中的限制所代表的生成函数列出来(具体我们讲题的时候解释):

    [egin{array}{l} 1+x^{6}+x^{12}+cdots=frac{1}{1-x^{6}} \ 1+x+x^{2}+cdots+x^{9}=frac{1-x^{10}}{1-x} \ 1+x+x^{2}+cdots+x^{5}=frac{1-x^{6}}{1-x} \ 1+x^{4}+x^{8}+cdots=frac{1}{1-x^{4}} \ 1+x+x^{2}+cdots+x^{7}=frac{1-x^{8}}{1-x} \ 1+x^{2}+x^{4}+cdots=frac{1}{1-x^{2}} \ 1+x=frac{1-x^{2}}{1-x} \ 1+x^{8}+x^{16}+cdots=frac{1}{1-x^{8}} \ 1+x^{10}+x^{20}+cdots=frac{1}{1-x^{10}} \ 1+x+x^{2}+x^{3}=frac{1-x^{4}}{1-x} end{array}]

    然后把他们全部乘起来,得到

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

    有一个这样子的结论(广义二项式定理):

    [frac{1}{(1-x)^{n}}=sum_{i=0}^{infty} {{n+i-1} choose {i}} x^{i} ]

    那么我们上面得到的式子就是 (n=5) 的情况,所以:

    [frac{1}{(1-x)^{5}}=sum_{i=0}^{infty} {{i+4} choose {i}} x^{i} ]

    所以答案就是 ({n+4} choose {n}),这题做完了。

    凑合着放一下代码

    n=int(input())
    print((n+1)*(n+2)*(n+3)*(n+4)//24)
    

    你问我为啥写 (Python)?
    是不可能写高精度的,这辈子都不可能再写高精度的
    UPD. (Py)被卡了,所以还是老实写高精压位或者 (ntt) 优化吧/kk

    完结撒花!!!

  • 相关阅读:
    AJAX异步传输——以php文件传输为例
    js控制json生成菜单——自制菜单(一)
    vs2010中关于HTML控件与服务器控件分别和js函数混合使用的问题
    SQL数据库连接到服务器出错——无法连接到XXX
    PHP错误:Namespace declaration statement has to be the very first statement in the script
    【LeetCode】19. Remove Nth Node From End of List
    【LeetCode】14. Longest Common Prefix
    【LeetCode】38. Count and Say
    【LeetCode】242. Valid Anagram
    【LeetCode】387. First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/lgj-lgj/p/13466909.html
Copyright © 2020-2023  润新知