生成函数简介

生成函数 \(\text{(generating function)}\),又称母函数,是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息。
by wiki

用人话来说生成函数就是把一个序列变成了一个函数。

一个形如 \(F(x) = \sum_{n > 0}{a_n \times x^n}\) 的函数可以理解为他是一个每一项分别为 \(a_n\) 的序列。

普通生成函数

重新引用上面的定义 \(F(x) = \sum_{n > 0}{a_n \times x^n}\)

这个 \(n\) 的定义域是到正无穷的,因为在序列的意义下,不存在的项的系数即为 \(0\),代回带函数里面也不影响。

关讲过于抽象,举几个栗子(我们定义 \(a\) 为序列, \(F(x)\) 为它的生成函数)。

  • \(a = [1, 2, 3]\)\(F(x) = 1 + 2 \times x + 3 \times x ^ 2\)

  • \(a = [1, 1, 1 …]\)\(F(x) = \sum_{n >= 0}{x ^ n}\)

  • \(a = [1, 2, 4 …]\)\(F(x) = \sum_{n >= 0}{2 ^ n \times x ^ n}\)

  • \(a = [1, 3, 5 …]\)\(F(x) = \sum_{n >= 0}{(2 \times x + 1) \times x ^ n}\)

通过上面的很多栗子,相信大家可以发现函数每一项的系数就是序列的每一项的值。

接下来有一些很 \(naive\) 的运算法则。

由于序列之间的运算是项项相对应的。

所以数字之间满足的运算法则,在生成函数里面也一样适用。

运算法则

1.加法运算:

考虑对于 \(2\) 个普通的生成函数,他们的生成函数为 \(F(x)\)\(G(x)\)

\(F(x) + G(x) = \sum_{(a_n + b_n)} \times x ^ n\)

这样 \(F(x) + G(x)\) 是序列 \(a_n + b_n\) 的普通生成函数。

2.乘法运算:

考虑对于 \(2\) 个普通的生成函数,他们的生成函数为 \(F(x)\)\(G(x)\)

\(F(x) \times G(x) = \sum_{x ^ n} \sum_{i = 0}^{n}{a_i \times b_{n - i}}\)

这样 \(F(x) \times G(x)\) 是序列 \(a_n \times b_n\) 的普通生成函数。

但是写太多 \(\sum\) 会显得整个柿子特别的丑陋,所以就有了封闭形式。

\(a = [1, 1, 1 …]\) 为例,它的生成函数是 \(F(x) = \sum_{n >= 0}{x ^ n}\)

那么我们进一步化简可以得到 \(F(x) * x + 1 = F(x)\)

移项可得 : \(F(x) = \frac{1}{1 - x}\)

就不再一一赘述,如果想要进一步理解的可以看 wiki 上的小练习,上面从从易到难,有求导,二项式定理,数学归纳法……运用。

斐波拉契数列

有一个非常著名而且经典的序列叫斐波拉契数列。

他的递推式是这个样子的:\(f(x) = f(x - 1) + f(x - 2)\)

咋一看这个式子就感觉它很不好推是吧,但是我们有项数之间的数量关系对吧,那么就可以很容易的推出它的封闭形式。

\(f(x) = x \times f(x) + x ^ 2 \times f(x) - a_0 \times x + a_1 \times x + a_0\)

这个柿子可以理解为把 \(f(x)\) 右移一位和右移两位的结果相加,并且补上那些移项所消失的项。

即:\(f(x) = \frac{x}{1 - x - x ^ 2}\)

我们可以把封闭形式暴力分解:

\(f(x) = \frac{x}{1 - x - x ^ 2} = \frac{x}{(1 - \frac{1 - \sqrt{5}}{2}) x \times (1 - \frac{1 + \sqrt{5}}{2}) x}\)

\(u = \frac{1}{1 - \frac{1 - \sqrt{5}}{2}}, v = \sqrt{5}\)

那么原始可以化简为:\(\frac{x}{u \times (u + v)} = \frac{u}{v} \times (\frac{1}{u} - \frac{1}{u + v})\)

带回即可得 : \(\frac{x}{(1 - \frac{1 - \sqrt{5}}{2}x) \times (1 - \frac{1 + \sqrt{5}}{2}x)}\)

化简可得 : \(\frac{1}{\sqrt{5}} \times ((\frac{1 + \sqrt{5}}{2}) ^ n) - (\frac{1 - \sqrt{5}}{2}) ^ n)\)

也就是我们常见的形式。

封闭形式转化为展开形式

先咕着

一些例题

洛谷P2000 拯救世界

题解:

经典的生成函数入坑题。

对于题目里描述的 \(10\) 种召唤方法,我们分别计算他的封闭形式并相乘,然后转化为展开形式并且求第 \(n\) 的系数就行了。

\(\text{kkk}\)

  • 金:\(1 + x ^ 6 + x ^ {12} … = \frac{1}{1 - x ^ 6}\)

  • 木:\(1 + x ^ 2 + … + x ^ 8 = \frac{1 - x ^ {10}}{1 - x}\)

  • 水:\(1 + x ^ 2 + … + x ^ 4 = \frac{1 - x ^ 5}{1 - x}\)

  • 火:\(1 + x ^ 4 + x ^ 8 + … = \frac{1}{1 - x ^ 4}\)

  • 土:\(1 + x ^ 2 + … + x ^ 6 = \frac{1 - x ^ 6}{1 - x}\)

\(\text{lzn}\)

  • 金:\(1 + x ^ 2 + x ^ {4} … = \frac{1}{1 - x ^ 2}\)

  • 木:\(1 + x = \frac{1 - x ^ {2}}{1 - x}\)

  • 水:\(1 + x ^ 8 + x ^ 16 = \frac{1}{1 - x ^ 8}\)

  • 火:\(1 + x ^ 10 + x ^ 20 + … = \frac{1}{1 - x ^ 10}\)

  • 土:\(1 + x ^ 2 + x ^ 3 = \frac{1 - x ^ 4}{1 - x}\)

很多项都可以约掉,最后得到的就是:\(\frac{1}{(1 - x) ^ 5}\)

这个东西要怎么展开呢?

\(\frac{1}{(1 - x) ^ 5} = (\frac{1}{1 - x}) ^ 5 = C_{n + 4} ^ {4} = (n + 1) \times (n + 2) \times (n + 3) \times (n + 4) / 24\)

这个东西要用高精或者 \(\text{NTT}\) ,当然 \(\text{ruby}\) 还是更香的。