生成函数
Posted morning-glory
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成函数相关的知识,希望对你有一定的参考价值。
一般生成函数(OGF)
引入
考虑一类组合对象组成的集合\\(A\\),其中:
- 每个元素\\(a\\in A\\)都被定义了“大小”\\(|a|\\),它是一个非负整数。
- 对于给定的\\(n\\),大小为\\(n\\)的元素的数量是有限的,记作\\(A_n\\)
eg. \\(A\\)是全体\\(01\\)串组成的集合,一个\\(01\\)串的大小被定义为它的长度则\\(A_n=2^n\\)
定义
\\(A\\left( x\\right) =\\sum ^\\infty _i=0A_ix^i\\)
为\\(A\\)的一般生成函数
注意
- \\(A(x)\\)为一个多项式
- 这里的\\(A_i\\)为第\\(i\\)项的 系数
这是一个形式幂级数,不用考虑何时收敛
这里的\\(x^i\\)为形式幂,无实义,一般也不会去求
但是\\(x^i\\)有区分实际意义的作用,即\\(x^i\\rightarrow\\)第\\(i\\)项
\\(x^i\\)的系数为第\\(i\\)种状态的答案
这个不好说,举个例子
eg.
\\(A\\)是全体\\(01\\)串组成的集合,则
\\(\\beginalignedA\\left( x\\right) =\\sum ^\\infty _i=02^ix^i\\endaligned=\\dfrac11-2x\\)
最后一步是用的等比数列求和公式,不用考虑何时收敛,所以认为其很大是趋近于0
其中\\(A_i=2^i\\),表示长度为\\(i\\)的答案为\\(2^i\\)
\\(x^i\\)的系数就是长度为\\(i\\)的答案,它是用于区分这个的
运算
有两类组合对象\\(A\\)和\\(B\\)
- 定义\\(C\\)为\\(A\\)和\\(B\\)的并集
\\(C(x) =A(x) +B(x),O(n)\\)计算 - 定义\\(D\\)为\\(A\\)和\\(B\\)的笛卡尔积,也即\\(D\\)中每个元素\\(d\\)都是\\(A\\)中某元素\\(a\\)与\\(B\\)中某元素\\(b\\)拼成的二元组\\((a,b)\\),其大小\\(|d|\\) 定义为\\(|a|+|b|\\)
\\(D(x) =A(x)B(x)\\),\\(FFT\\)乘法\\(O(nlogn)\\)计算
eg:
\\(A\\)是全体\\(01\\)串组成的集合,\\(B\\)是全体字母组成的集合
\\(\\beginalignedA\\left( x\\right) =\\sum ^\\infty _i=02^ix^i\\endaligned=\\dfrac11-2x\\)
\\(\\beginalignedB\\left( x\\right) =\\sum ^\\infty _i=026^ix^i\\endaligned=\\dfrac11-26x\\)
\\(C(x)=A(x)+B(x)\\),\\(C(x)\\)表示全体\\(01\\)串与全体字母的并集
\\(C(x)\\)中\\(x^i\\)项的系数表示长度为\\(i\\)的\\(01\\)串与字符串有多少
\\(D(x)=A(x)B(x)\\),\\(D(x)\\)表示\\(01\\)串与字符串拼接出的串(前面是\\(01\\)串,后面是字符串)
\\(D(x)\\)中\\(x^i\\)项的系数表示长度为\\(i\\)的拼接出的串有多少
其中某串长度可以为0
个人理解
我们发现上面的例题中的\\(D\\)如果我们不考虑多项式
自己暴力的去算,也有这样的公式
\\(\\beginaligned\\sum_i+j=na_ib_j\\endaligned\\)
其中\\(a_i\\)表示长度为\\(i\\)的\\(01\\)串有多少种,\\(b_j\\)表示长度为\\(j\\)的字符串有多少种
然后我们可以发现长度\\(i+j\\)的答案会由\\(i\\)与\\(j\\)项得到,再发现其与指数乘法有相似之处,即\\(x^ix^j=x^i+j\\),之后就想到将答案存为其系数,\\(x^i\\)表示实际意义,于是就可以用多项式来解决问题,因为多项式可以\\(FFT\\)优化,比暴力快很多
(我觉得生成函数可能就是这么来的.....)
指数生成函数(EGF)
引入
有时我们需要考虑带标号的组合对象,比如图
\\(n\\)个点的标号图,顶点的标号恰好为\\(1\\sim n\\)
带标号对象的拼接
将两个对象\\(a;b\\)拼接起来,\\(|a|=n,|b|=m\\)
- 无标号时,只有一种方法
- 带标号时,规定拼接时拼接对象内部相对标号顺序不变,而互相的标号
可以改变,则有\\(C_n+m^n(\\beginpmatrix n+m \\\\ n \\endpmatrix)\\)种拼接方法
因为只要考虑前\\(a\\)中的\\(n\\)个用了哪些标号,剩下的\\(m\\)个给\\(b\\)中的\\(m\\)个,答案唯一,而对象内部相对标号顺序不变,所以得到的标号如何分配也是唯一的
eg.
将\\(213,21\\)(每个数字是一个标号)拼接,有\\(10\\)种方法
数字表示分配的标号
\\(435,21|\\ 425,31|\\ 325,41|\\ 324,51|\\ 415,32\\)
\\(315,42|\\ 314,52|\\ 215,43|\\ 214,53|\\ 213,54\\)
如第一种方案\\(435\\)对应的\\(231\\)相对标号顺序不变,\\(31\\)对应的\\(21\\)相对标号顺序也不变
定义
对于带标号组合对象组成的集合\\(A\\),定义
\\(\\beginalignedA\\left( x\\right) =\\sum _i= 0^nA_i\\dfrac x^ii!\\endaligned\\)
为\\(A\\)的指数生成函数
运算
有两类组合对象\\(A\\)和\\(B\\)
- 定义\\(C\\)为\\(A\\)和\\(B\\)的并集
\\(C(x) =A(x) +B(x),O(n)\\)计算 - 定义\\(D\\)为\\(A\\)和\\(B\\)的笛卡尔积,也即\\(D\\)中每个元素\\(d\\)都是\\(A\\)中某元素\\(a\\)与\\(B\\)中某元素\\(b\\)拼成的二元组\\((a,b)\\),其大小\\(|d|\\) 定义为\\(|a|+|b|\\)
\\(D(x) =A(x)B(x)\\),\\(FFT\\)乘法\\(O(nlogn)\\)计算
没错,就是复制上面的内容
对于\\(D(x)\\)
\\(\\beginalignedD(x)=\\sum _i+j=nA_iB_j\\dfrac \\left( i+j\\right) !i!j!\\endaligned\\)
\\(\\beginaligned\\dfrac D(x)n!=\\sum _i+j=n\\dfrac Aii!\\dfrac B_jj!\\endaligned\\)
所以乘法运算成立
个人理解
如引入中的问题
用一般生成函数来求解
\\(\\beginalignedD\\left( x\\right) =A\\left( x\\right) B\\left( x\\right) =\\sum ^n_i+j=nA_i\\cdot B_j\\beginpmatrix n \\\\ i \\endpmatrix\\endaligned\\)
最后又化简成
\\(\\beginaligned\\dfrac D(x)n!=\\sum _i+j=n\\dfrac Aii!\\dfrac B_jj!\\endaligned\\)
于是我们就弄出一个指数生成函数方便运算且省去求组合数
以下\\(A\\)为生成函数
生成序列(seq)
如字面意思,要生成一个序列
序列的顺序是确定的
\\(\\beginalignedseq\\left( A\\right) =\\sum ^\\infty _i=0Ai=\\dfrac 11-A\\endaligned\\)
生成集合(set)
如字面意思,要生成一个集合
集合的顺序是无关紧要的,所以要除以全排列
\\(\\beginalignedset\\left( A\\right) =\\sum ^\\infty _i=0\\dfracA^ii!=e^A\\endaligned\\)
最后一步是因为该式子符合\\(e^x\\)的泰勒展开
关于泰勒展开可看我的该篇博客泰勒公式于牛顿迭代
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧
以上是关于生成函数的主要内容,如果未能解决你的问题,请参考以下文章