前言
之前一直无法理解生成函数的这些概念,最近算是入了门,下面我记录下我自己理解这些式子的方式。
我们使用生成函数的最终目的是计数,所以多项式的项次数超过某个值对于我们来说就没用了,于是我们可以在(modxn) 的意义下理解逆元、复合等概念。
常生成函数
一个数列 {an} 对应的常生成函数为 A(x)=∑n≥0anxn。
有两种物体,取 i 个第一种物体的方案数为 ai,取 j 个第二种物体的方案数为 bj,那么取 k 个物体的方案数 ck=∑i=0kaibk−i,这也称为这两个序列的卷积。
我们观察两个常生成函数的积,有:
[xk]A(x)B(x)=i=0∑kaibk−i
于是 A(x)B(x) 就是 ck 的常生成函数。
指数生成函数
一个数列 {an} 对应的指数生成函数为 A(x)=∑n≥0ann!xn。
有两种物体,取 i 个第一种物体的方案数为 ai,取 j 个第二种物体的方案数为 bj,那么取 k 个物体排成一列的方案数 ck=∑i=0k(ik)aibk−i。
我们观察两个指数生成函数的积,有:
[xk]A(x)B(x)=i=0∑ki!ai(k−i)!bk−i=i=0∑k(ik)aibk−ik!1
于是 A(x)B(x) 就是 ck 的指数生成函数。
定义 exp(ax)≡∑i=0n−1i!aixi(modxn),下面我们证明 exp(ax)exp(bx)≡exp((a+b)x)(modxn):
exp(ax)exp(bx)≡k=0∑n−1(i=0∑ki!(k−i)!aibk−i)xk≡k=0∑n−1(i=0∑k(ik)aibk−i)k!xk≡k=0∑n−1k!(a+b)kxk(modxn)
逆元
对于 A(x),满足 A(x)B(x)≡1(modxn) 的多项式称为 A(x) 的逆元。
我们可以假设 A(x)=∑i=0n−1aixi,B(x)=∑i=0n−1bixi,然后相乘,可以得到:
A(x)B(x)≡k=0∑n−1(i=0∑kaibk−i)xk(modxn)
现在就可以列方程求解了:
⎩⎨⎧a0b0a0b1+a1b0⋮∑i=0n−1aibn−1−i=1=0=0
所以 b0=a0−1,并且递推能唯一地解出每一个 bi 的值,所以逆元是唯一的。
下面给出常见的逆元:
-
A(x)=∑i=0n−1xi 和 B(x)=1−x;
即 a={1,1,1,…,1} 与 b={1,−1,0,…,0},容易验证这满足条件。
-
A(x)=∑i=0n−1kixi 和 B(x)=1−kx;
即 a={k0,k1,k2…,kn−1} 与 b={1,−k},容易验证这满足条件。
-
A(x)=∑i=0n−1(k−1k−1+i)xi 和 B(x)=(1−x)k;
这里用了前面的结论 (1−x)−1≡∑i=0n−1xi(modxn),考虑:
(1−x)k×((1−x)−1)k≡1(modxn)
于是就有:
((1−x)k)−1≡(i=0∑n−1xi)k(modxn)≡j=0∑n−1cjxj(modxn)
考虑每一个 cj 的意义,是在 k 个非负数 i1,i2,…,ik 满足 i1+i2+⋯+ik=j 的解的个数,那么显然有 cj=(k−1j+k−1)。
卡特兰数
n+1 个数相乘 x0x1…xn,求它们结合顺序的方案数。如 n=3 时,x0(x1(x2x3)),x0((x1x2)x3),(x0x1)(x2x3),((x0x1)x2)x3,(x0(x1x2))x3。
首先,c0=1,c1=1。
对于 cn,考虑最后一步运算,一定是左右两个组内都乘完之后进行的,那么我们可以枚举这两个组的分界线的位置,就得到了公式 cn=c0cn−1+c1cn−2+⋯+cn−1c0。
考虑这个序列的常生成函数 F(x)≡∑i=0n−1cixi(modxn),我们能得到什么信息?
根据这个递推式,不难看出这是一个卷积的形式,那么我们给 F(x) 平方一下,可以推出:
F2(x)≡k=0∑n−1(i=0∑kcick−i)xk≡k=0∑n−1ck+1xk(modxn)
我们给两边同乘一个 x,有:
xF2(x)≡k=1∑n−1ckxk≡F(x)−1(modxn)
所以我们需要解方程 xF2(x)−F(x)+1≡0(modxn)。
按照传统配方的思路,可以得到 (xF(x)−21)2≡−x+41(modxn+1)。
对于所有函数 G(x) 满足 G2(x)≡−x+41(modxn+1),我们有 xF(x)≡G(x)+21(modxn+1)。
设 G(x) 对应的序列为 {g0,g1,…,gn},我们有:
⎩⎨⎧g02g0g1+g1g0⋮∑i=0ngign−i=41=−1=0
我们希望 g0=−21,否则 xF(x)≡G(x)+21(modxn+1) 是无解的。
于是 gi 的每一个值都可以唯一地确定下来了,并且有 F(x) 的序列 {f0,f1,…,fn−1} 满足 fi=gi+1。
根据广义二项式定理,有:
(−x+41)21≡i=0∑ni!(21)i(−x)i(41)21−i(modxn+1)
本文不讨论为什么可以把高数的东西拿过来用,只证明这个式子是对的。
−x+41≡k=0∑n(i=0∑k(i21)(k−i21))(−1)k(41)1−kxk≡k=0∑n(k1)(−1)k(41)1−kxk≡41−x(modxn+1)
这里用到了范德蒙德卷积,它对于上指标是实数的情况仍然是成立的。
于是我们就得到了 gi 的解:
gi=−i!(21)i(−1)i(41)21−i=−21i!(21)i(−4)i
当 i≥2 时,我们可以看到 (21)i=21(−21)⋯(21−i+1) 有 i−1 个负项,加上式子最前面的符号,可以把 (−4)i 的负号全部抵消掉,并且有:
gi=i!(21)i−14i−1=i!(1×3×⋯×(2i−3))2i−1=i!(i−1)!(1×3×⋯×(2i−3))(1×2×⋯×(i−1))2i−1=i!(i−1)!(1×3×⋯×(2i−3))(2×4×⋯×(2i−2))=i1(i−1)!(i−1)!(2i−2)!=i1(i−12i−2)
于是 fi=gi+1=i+11(i2i),可以验证 i=0 时是成立的。
说明
虽然上面我们都是在模 xn 的意义下讨论的,实际上做题的时候可以认为 n 足够大,把生成函数写成 F(x)=∑i≥0fixi 的形式即可。
[CF451E] Devu and Flowers
对于每一种花,它的常生成函数是 Fi(x)=(1−xfi+1)(1−x)−1,于是答案的生成函数 F(x)=(1−x)−n∏i=1n(1−xfi+1)。
设 A(x)=(1−x)−n,B(x)=∏i=1n(1−xfi+1),由于 n≤20,所以可以暴力算出 B(x),二进制枚举每一个括号给出的贡献即可,这最多会生成 2n 项,计算的复杂度是 O(n2n)。
我们又知道 A(x) 的每一项是 (n−1n−1+i),所以枚举 B(x) 的每一项,O(n) 暴力计算组合数即可,复杂度 O(n2n)。
AC Code。
[CEOI2004] Sweets
这和上一个题目几乎一样,只不过对于答案的生成函数 F(x),需要求 ∑i=ab[xi]F(x)。
考虑 G(x)=∑i≥0gixi 其中 gi=∑j=0ifj。
令 h={1,1,1,…} 就 G(x)=F(x)H(x),所以我们给 F(x) 再乘一个 (1−x)−1 即可。
这里有一个别的问题,我们怎么求 (nn+i)mod2004?
写一下它的式子:
(nn+i)=n!(n+i)n
由于组合数一定是整数,所以 n!∣(n+1)n,先算 r=(n+i)nmod(2004n!),我们有:
(n+i)n=q(2004n!)+r
其中 n!∣r,于是:
n!(n+i)n=q(2004!)+n!r
AC Code。
[POJ3734] Blocks
对于 a={1,0,1,0,…} 的指数生成函数,为 F1(x)=1+2!x2+4!x4+⋯=2exp(x)+exp(−x);对于奇偶都行的为 F2(x)=exp(x),所以答案的指数生成函数就是:
F(x)=(F1(x)F2(x))2=(2exp(x)+exp(−x)exp(x))2=4exp(4x)+2exp(2x)+1
由于我们要求 n![xn]F(x),其中 n≥1,所以可以不用管那个常数项。
继续计算:
n![xn]F(x)=4n!(n!4n+2n!2n)=44n+2n+1
AC Code。
[CF891E] Lust
观察操作前后的序列,我们会发现,操作前是 a1a2…ax−1axax+1…an,操作后是 a1a2…ax…an−a1a2…ax−1ax+1…an,于是 res 就加它们两个之差。
我们假设 k 次操作后 ai←ai−bi,其中 bi≥0,那么就有期望 E 为:
E=nk∑b1+⋯+bn=k(∏i=1nai−∏i=1n(ai−bi))(b1,b2,…,bnk)=nkk!(b1+⋯+bn=k∑(i=1∏nbi!ai)−b1+⋯+bn=k∑(i=1∏nbi!ai−bi))
不难看出 ∑b1+⋯+bn=k∏i=1nbi!∗ 是一个卷积的结构,手玩一下可以推出左边是 aiexp(x) 乘起来,右边是 (ai−x)exp(x) 乘起来,这都是可以 O(n2)计算的,最后取 xk 的系数。
形式化地,我们写作:
E=[xk]nkk!(i=1∏naiexp(x)+i=1∏n(ai−x)exp(x))=[xk]nkk!exp(nx)(i=1∏nai+i=1∏n(ai−x))=[xk]nkk!exp(nx)F(x)=nkk!i=1∑n[xi]F(x)[xk−i]exp(nx)=nkk!i=1∑n[xi]F(x)(k−i)!nk−i=nk1i=1∑n[xi]F(x)nk−i(k−i)!k!
我们可以 O(n) 算出 (k−i)!k!,由于 F(x) 的次数最高就是 n,于是我们的 i 最大到 n 即可,这样的复杂度是 O(n2) 的。
AC Code。