生成函数
生成函数简介
生成函数 \(\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}\) 还是更香的。