前言
形式幂级数的本质是一个无穷数列,然后我们对其进行定义了一系列操作进行变换。
我们一般不关心其是否收敛,但是有很多微积分中要求收敛的条件下才成立的公式在这里仍然成立,本文不关心它们为什么成立,只是拿来用。
常生成函数
一个数列 {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 的指数生成函数。
逆元
对于 A(x),满足 A(x)B(x)=1 的多项式称为 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
现在就可以列方程求解了:
⎩⎨⎧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;
考虑:
(x−11)k=(i≥0∑xi)k=i≥0∑cixi
考虑每一个 cj 的意义,是在 k 个非负数 i1,i2,…,ik 满足 i1+i2+⋯+ik=j 的解的个数,那么显然有 cj=(k−1j+k−1)。
[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)。
[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
[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
[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) 的。
[P8594] 一个仇的复
只有 1×2 的矩形可以竖着放,别的我们都认为是横着放的,包括 1×1。
既然如此,不妨枚举竖着放的 1×2 的矩形的数量 i,以及它们划分出来的非空段的数量 1≤j≤i+1。
一个长度为 l 的非空段如果要贡献 p 个矩形,方案数等价于在 2l−2 个空隙中选择 p−2 个,因此生成函数为:
p≥2∑(p−22l−2)xp=x2i=0∑2l−2(i2l−2)xi=x2(1+x)2l−2
那么所有非空段长度之和为 n−i,那么选 k−i 个矩形的方案数就是:
[xk−i]x2j(1+x)2(n−i)−2j(j−1n−i−1)(ji+1)
这里的组合数来自于两个地方。
- 设非空段的长度为 l1,l2,…,lj,那么 ∑k=1jlk=n−i 的正整数解的数量是 (j−1n−i−1)
- 设非空段的缝隙(包括第一个前面和最后一个后面)中 1×2 矩形的数量为 x0,x1,…,xj,那么 x0,xj≥0,x1,x2,…,xj−1≥1,并且 ∑k=0jxj=i 的解的数量是 (ji+1)。
注意特判 i=n 的情况,此时只能是 n=k 时有 1 种方案,否则有 0 种。
接下来化简式子:
[n=k]+i=0∑min(n−1,k)j=1∑i+1(ji+1)(k−i−2j2(n−i)−2j)(j−1n−i−1)
复杂度 O(k2)。
[TJOI2015] 概率论
设 Ei 表示节点数为 i 的二叉树的子节点期望,初始化 E0=0,E1=1。
设 fi 表示节点数为 i 的二叉树数量,初始化 f0=f1=1。
枚举其左儿子的节点数量,那么有递推式:
Ei=fi1j=0∑i−1fjfi−1−j(Ej+Ei−1−j)
至于 fi,众所周知这是卡特兰数的递推式:
fi=j=0∑i−1fjfi−1−j
为了尽量简化式子,我们合并 Eifi=hi,那么有:
hi=j=0∑i−1fi−1−jhj+fjhi−1−j=2j=0∑i−1fi−1−jhj
令 f 的生成函数是 F(x),h 的生成函数是 H(x),能够写出 i≥2 的递推:
[xi]H(x)=2j=0∑i−1[xi−1−j]F(x)[xj]H(x)=2[xi−1]F(x)H(x)=2[xi]xF(x)H(x)
根据 h0=0,h1=1 得到 H(x) 的最低次数是 1,F(x) 的最低次数是 0,所以能够写出:
H(x)=2xF(x)H(x)+x
根据卡特兰数的生成函数 F(x)=2x1−1−4x,代入化简得到 H(x)=1−4xx。
展开幂级数,得到通项公式:
H(x)=xi≥0∑(i−21)(−4x)i=i≥0∑(−21)ii!(−4)ixi+1=i≥0∑2i(2i−1)!!i!4ixi+1
到这里,我们需要用到化简卡特兰数通项时的一个技巧,是双阶乘与阶乘之间的关系:
(2n−1)!!2n!=2⋅4⋯2n=2nn!
继续化简:
H(x)=i≥0∑2i(i!2i)2i!i!4ixi+1=i≥0∑i!i!2i!xi+1
于是我们得到 hn=(n−12n−2),又因为 fn=n+11(n2n),那么得到:
P=n+11(n2n)(n−12n−2)=2(2n−1)n(n+1)
复杂度 O(1)。
[FJOI2016] 建筑师
设 fj,i 表示长度为 i 的排列中,从最左边开始能看到 j 个建筑的方案数。
显然我们的递推过程是类似笛卡尔树的操作,枚举一个最大值,那么最大值左边就是一个独立的子问题,右边随便放。
于是可以写出转移:
fj,i=k=1∑i(k−1i−1)fj−1,k−1(i−k)!=k=1∑i(i−1)!(k−1)!fj−1,k−1
定义 gj,i=fj,i/i!,可以得到:
gj,i=i1k=1∑igj−1,k−1=i1k=0∑i−1gj−1,k
设 gj 的生成函数为 Gj(x),那么可以得到转移:
[xi]Gj(x)=i1[xi−1]1−xGj−1(x)=[xi]∫1−xGj−1(x)dx
我们看一下 j=0,1 时数列是什么样:当 j=0 时,只有 f0,0=1;当 j=1 时,f1,i=(i−1)!,那么 g1,i=1/i。
于是可以看出 G1(x)=−ln(1−x),根据递推式不难看出 Gj(x)=j!(−ln(1−x))j。
此时来看我们要回答的询问是什么,依然枚举最大值的位置:
i=1∑n(i−1n−1)fA−1,i−1fB−1,n−i=i=1∑n(i−1n−1)(i−1)!(n−i)!gA−1,i−1gB−1,n−i=(n−1)!i=1∑ngA−1,i−1gB−1,n−i=(n−1)![xn−1]GA−1(x)GB−1(x)=(n−1)!(A−1)!(B−1)!(A+B−2)![xn−1]GA+B−2(x)
但是我们不需要真的用 Gj(x) 的公式求其通项,暴力 O(nmax(A+B)) 预处理即可,每次询问 O(1) 回答。
[JLOI2015] 骗我呢
每一行的差分至多有一个 2,其余位置都是 1,不妨将没有 2 视作 2 的位置在 m+1。
于是每行 2 的位置 pi 需要满足 pi≥pi−1−1。
于是可以很快写出一个 O(nm) 的做法:设 fi,j 表示第 i 行 pi=j 的方案数,那么转移如下:
fi,j={∑k=1j+1fi−1,k∑k=1m+1fi−1,kj≤mj=m+1
对于第一行,有 f1,1∼f1,m+1=1。
如果对每行建立生成函数,转移存在前后截断的问题,难以写出一个统一的表达式,所以我们应该按列建立生成函数。
定义 Fj(x)=∑i≥1fi,jxi−1,那么对 i=2∼m 有:
Fi−Fi−1=xFi+1
同时,有 Fm=Fm+1,所以我们可以得到递推:
Fi−1=Fi−xFi+1
设 Fi=DiFm,那么有 Dm=Dm+1=1,并且:
Di=Di+1−xDi+2
求出 D1 后,代入 F1=x(F1+F2)+1 就有:
Fm=D1−xD1−xD21
为了习惯我们从小到大递推的习惯,代换 Gi=Dm+1−i,我们的目标式就变成了:
Fm=Gm−xGm−xGm−11=Gm+21
那么我们的问题就变成了,已知 G0=G1=1,并且 Gi=Gi−1−xGi−2,求 [xn+1]Fm。
待定系数法解决这个递推式:
Gi−λGi−1=(1−λ)(Gi−1−1−λxGi−2)
定义 Hi=Gi/λi,则有:
Hi−Hi−1=λ1−λ(Hi−1−Hi−2)
并且我们一开始就可以解出 x=λ(1−λ),不过我们可以先关注 Hi 的式子。
由于 H0=1,H1=1/λ,设 t=(1−λ)/λ,可以推出 Hi−Hi−1=ti,于是 Hi=1+t+t2+⋯+ti。
所以我们可以解出 Gi:
Gi=λiHi=(t+11)i1−t1−ti+1
因此我们现在得到了 Fm 的表达式:
Fm=Gm+21=1−tm+3(1−t)(1+t)m+2
问题是这是关于 t 的式子,我们需要拉格朗日反演求出 [xn]Fm=fn+1,m。
具体地说,由于 t=(1+t)2x,那么设 H(t)=Fm,有:
[xn]H(t)=n1[tn−1]H′(t)(1+t)2n
注意,我们这里不需要真的对分式函数 H 进行求导,因为我们只需要提取它的系数,所以利用 (uv)′=u′v+uv′ 公式可以得到:
[xn]H(t)=n1[tn−1](H(t)(1+t)2n)′−n1[tn−1]H(t)2n(1+t)2n−1=[tn]H(t)(1+t)2n−2[tn]tH(t)(1+t)2n−1=[tn]H(t)(1+t)2n−1(1−t)=[tn]1−tm+3(1−t)2(1+t)m+2n+1
因此,答案就是:
k≥0∑(n−k(m+3)m+2n+1)−2(n−1−k(m+3)m+2n+1)+(n−2−k(m+3)m+2n+1)
非法组合数取 0,复杂度 O(n+m)。