题意
有 d 天,每天可以选择花费 1/3/4/6 元购买四种不同的零食,求 d 天总共恰好花费 n 元的购买方案数。
两个购买方案不同当且仅当存在一天购买的零食不同.
d≤2×105,n≤106。
解法
定义:
普通生成函数(OGF):一个序列 ⟨an⟩ 的 OGF 是一个形式幂级数(可以看作无限长的多项式)A(x)=∑i=0∞aixi,其中 ai 是数列的第 i 项。
通过类比一般多项式的乘法,可以得到 OGF 的加法和乘法。
设 a,b 的 OGF 分别是 F(x),G(x),则:
- OGF 的加法:F(x)+G(x) 对应的数列是 ⟨an+bn⟩。
- OGF 的乘法:F(x)G(x) 对应的数列是 ⟨∑i=0naibn−i⟩。
在形式幂级数中,我们不关心 x 的具体取值,只关心系数的含义,就相当于把系数挂在了一个多项式上,再用这个多项式去进行进一步的各种计算。
而多项式的乘法就是一种卷积,当我们要找 x2 的系数时,就是找 x0 和 x2 的系数相乘加上 x1 和 x1 的系数相乘再加上 x2 和 x0 的系数相乘。这正好对应了把总数为 2 的物品分成两部分去计数的过程。所以,我们要把花费放在指数上,而方案放在系数上,这样就可以通过多项式乘法来进行计数。
举例:
有 3 块红色的地砖和 2 块蓝色的地砖,求选出 4 块地砖的方案数(两个方案不同当且仅当选出的红砖个数不同或选出的蓝砖数量不同)。
手动枚举一下,可能的方案只有 (3,1),(2,2),所以答案是 2。
用 OGF 解决这个问题,写出红色地砖的 OGF:R(x)=1+x+x2+x3,表示选 0/1/2/3 块红色地砖的方案数分别是 1/1/1/1。蓝色地砖的 OGF 是 B(x)=1+x+x2。所以最后的答案就是 [x4]R(x)B(x),其中 [xn]F(x) 表示形式幂级数 F(x) 中 xn 的系数。相乘,结果为 R(x)B(x)=1+2x+3x2+3x3+2x4+x5,所以答案是 2。
可以发现,我们顺带求出了需要选出任意块地砖的各自方案数。
回到本题,我们的序列第 i 个元素表示花费 i 元的购买方案数。则每一天的 OGF 就是 x+x3+x4+x6,因为每一天可以选择花费 1/3/4/6 元购买零食。
所以总花费就是第一天花费加第二天花费加 … 加第 d 天花费,对应的 OGF 就是 (x+x3+x4+x6)d。因为每一天的选择规则都一样,且第一天的选择和第二天的选择是独立的,根据乘法原理,总方案数的 OGF 就是 d 个每天的 OGF 相乘。
那么,答案就是 [xn](x+x3+x4+x6)d。
后面稍微进行一些代数变形即可解决本题:
[xn](x+x3+x4+x6)d=[xn−d](1+x2+x3+x5)d=[xn−d](1+x2)d(1+x3)d
我们只需要枚举左边的项每一次的系数,就知道右边项对应的系数,通过二项式定理计算就可以解决本题。
答案即为
i,j∈N,2i+3j=n−d∑(id)(jd)
复杂度 O(d)。
参考代码。
题意
给定 n,求满足条件的非负整数四元组 (a,b,c,d) 个数:
- a+b+c+d=n;
- a∈{0,1};
- b∈{0,1,2};
- c 是偶数;
- d 是 3 的倍数。
0≤n≤109。
解法
一样的,写出每一个数的 OGF:
A(x)=1+x,B(x)=1+x+x2,C(x)=1+x2+x4+…,D(x)=1+x3+x6+…。
高中等比数列求和有如下公式:
i=0∑∞a1qi=1−qa1(∣q∣<1)
现在 C(x) 和 D(x) 是无穷级数,我们类比等比数列求和可以把它们写成封闭形式。
C(x)=i=0∑∞x2iD(x)=i=0∑∞x3i=1−x21=1−x31
在对形式幂级数进行运算时,我们不关心级数的敛散性,只关心每一项系数,所以可以直接使用这个公式, 1−x21 虽然看上去不像一个幂级数,但是它在形式幂级数的意义下,就是 ∑i=0∞x2i。 在运算时,使用分式会更加方便,我们也把这种形式叫做原来幂级数的封闭形式。
所以答案就是
[xn]A(x)B(x)C(x)D(x)=[xn](1−x2)(1−x3)(1+x)(1+x+x2)=[xn](1−x)21
接下来我们介绍如何求 [xn](1−x)k1。一个简单的方法是使用牛顿二项式定理(或泰勒展开),但是我们在此给出一种组合意义证明。
(1−x)k1=(∑n=0∞xn)k,我们考察 xn 的系数如何来的,就是要在每个括号中选择一个次数,使得总和为 n。这就相当于把 n 个相同的球放入 k 个不同的盒子中,允许某些盒子为空。根据插板法,答案就是 (k−1n+k−1)。
回到原题,答案就是 (2−1n+2−1)=n+1。
参考代码
题意
求满足条件的长度为 n 的序列个数:
- 每个元素是不大于 m 的非负整数;
- 总和为 s。
n,m,s≤2×105。
解法
答案是 [xs](1+x+…+xm)n。
进行代数变形:
[xs](1+x+…+xm)n=[xs](1−x1−xm+1)n=[xs](1−xm+1)n(1−x)−n.
之后只需要枚举两边系数即可,左右的系数我们都已经会处理了,答案就是
k=0∑n(−1)k(kn)(n−1s−k(m+1)+n−1).
参考代码
题意
求满足条件的长度为 n 的序列个数:
- 每个元素是不大于 m 的非负整数;
- 所有元素按从大到小排序之后,相邻的数奇偶性不同。
n,m≤2×105。
解法
对原数组 ⟨a⟩ 排完序之后得到 ⟨b⟩,考虑 ⟨b⟩ 的差分序列 ⟨d⟩:
di={b1,bi−bi−1i=1i>1
因为每个数都不同,只需要计算差分序列的个数,再乘以 n! 即可。
差分序列的条件如下:
- d1 是非负整数;
- d2,d3,…dn 是正奇数;
- d1+d2+…+dn≤m。
因此,这样的差分序列个数就是
i=0∑m[xi]1−x1(1−x2x)n−1=[xm−n+1](1−x)n+1(1+x)n−11.
(此处用到了如下性质:∑i=0m[xi]F(x)=[xm]1−xF(x),可以把 1−x1 看作一个前缀和算子)
参考代码
题意
求满足条件的长度为 n 的序列个数:
- 每个元素是不大于 m 的正整数;
- i 最多出现了 i 次。
n,m≤300。
解法
为解决本题,我们要介绍一种新的生成函数——指数生成函数(EGF)。
定义:
指数生成函数(EGF):一个序列 ⟨an⟩ 的 EGF 是一个形式幂级数 A(x)=i=0∑∞aii!xi,其中 ai 是数列的第 i 项。
可以得到 EGF 的加法和乘法的运算法则。
设 a,b 的 EGF 分别是 F(x),G(x),则:
- EGF 的加法:F(x)+G(x) 对应的数列是 ⟨an+bn⟩。
- EGF 的乘法:F(x)G(x) 对应的数列是 ⟨∑i=0n(in)aibn−i⟩。
我们发现,EGF 的乘法对应了不同物品组合的方案,也就自动解决了有序的问题。
写出每一个数的 EGF:Fk(x)=i=0∑ki!xi. 答案就是 [n!xn]i=1∏mFi(x)。
多项式用 NTT 做乘法,复杂度就是 O(nmlogn)。
参考代码
https://atcoder.jp/contests/fps-24/submissions/72985819