生成函数练习记录&题解
生成函数练习记录
前言
最近把nflsoj上的题都贺完了,之前既定要补的题也已完成,算是步入小康,终于有了点自己可以支配的时间了。
这篇markdown中会记录我这段时光写过的组合计数题目,大概都会与生成函数相关。
题目没有按照难度排序。
题目会给多个链接,用以照顾对OJ有不同口味的人士。
题目记录均会在通过题目后开始撰写,因此无法保证完全按照思考过程来,但正确性和逻辑性会比较好。
很可能有typo,有细节的纰漏亦可指出。
[HEOI2016/TJOI2016] 求和 洛谷 / LOJ
直接给出 \(\Theta(n)\) 做法
先把 \(j\) 枚举的范围提升到 \(n\) ,方便交换∑,并且保证斯特林数不变
斯特林数不便处理,并且后面正好有一个 \(j!\) 展开后可以消掉一项,用组合意义展开,这里发现即使当 \(j \geq i\) 的时候展开的结果还是对的
\(i\) 出现的最少,把它交换到里面去。
后面的那部分式子是生成函数的加法复合,使用生成函数表示出来
∑里左边那项可以 \(\log n\) 计算,用线性筛筛出质数位的幂后可以做到线性。右边那项把上面展开,然后短多项式求逆,也可以做到线性。
[NFLSOJ12776] 取胜 (来源:校内模拟赛,无链接,建议没见过这题的跳过)
生成函数部分题意,已知函数 \(F(x)\) 满足 \(F(x)=xe^{H(x)-F(x)+F(x) \cdot p0}\),其中p0为常量,\(H(x)= \sum\limits_{i\geq1}\dfrac{i^{i-1}}{i!}x^i\),也就是说,\(H(x)\) 是n个点有标号有根树的egf.
首先要知道一个性质,\(H(x)=xe^{H(x)}\),可以根据组合意义得出。
一下用 \(H^{-1}(x)\) 表示 \(H(x)\) 的复合逆,也就是说,\(H(H^{-1}(x))=H^{-1}(H(x))=x\) 不会用到复合逆的其他性质,只是在中间结果中借用它的存在。
然后大力化简,过程如下:
P.S. 通过 \(H(x)=xe^{H(x)}\) 可以把 \(exp\) 给去掉
然后我们要求这个式子的第 \(n\) 项。
后面那个式子的组合意义是 \(n\) 个点组成 \(i\) 个有根树的方案数乘 \(\dfrac{i!}{n!}\),除 \(n!\) 是因为egf,乘 \(i!\) 是因为选有根树是不讲究顺序的。
那么 \(n\) 个点组成 \(i\) 个有标号有根树,根据 \(\texttt{generalized Cayley's formula}\),直接得到方案数是 \(i\binom{n}{i}n^{n-i-1}\)
把这个结论带回去,计算完毕。
[HDU7147] Walk 杭电OJ
首先可以写出一个 dp,记录从某个格子到达最后一行的带权和。
可以发现每一列格子的转移式很相似,因此我们可以写出每一列的生成函数 \(G_i(x)\) 以及列上的前缀和 \(S_i(x)\),其中 \(G_i(x)\) 的第 \(j\) 项表示第 \(i\) 列从下往上第 \(j\) 个格子的 dp 值(下表从 0 开始)。
我们再设 \(d_i=S(S(S(i)))\) ,其中 S 的定义和题面中的一样。然后写出生成函数的式子。
这里会出现一个常数,比较丑陋,还会影响我们后期使用矩阵乘法时矩阵的大小,因此我们希望去掉它。这个常数产生的原因是最后一行的每个数都有一个初始贡献,我们可以在最后一行后面额外增加一行,然后强制要求终点是最后一行的第一个格子。
可以看出,当 \(d_i\) 非零时,这是一个项数很小的从右向左的递推式,因此转移可以写成矩阵的形式,同时矩阵中每个元素都是个次数较小的多项式,因此我们可以直接分治把这些矩阵乘起来。
当 \(d_i=0\) 时,直接从左向右暴力即可。
现在虽然我们不知道转移的初项 \(S_m(x)\) ,但是我们知道转移的末项,因此直接列出方程,求逆就能解出 \(S_m(x)\)
答案即为 \([x^n]S_m(x)\)
几点关于常数的事实:
- 矩阵乘法时先把矩阵所有元素 dft,乘完之后再 dft 回去,常数会乘上 \(1/3\)
- 当 \(d_i = 2\) 时,矩阵大小是 \(3 \times 3\) 的,但可以发现多项式的长度只有区间长度的 \(1/3\)。 而 \(d_i = 1\) 时,实际上可以把矩阵写成 \(2 \times 2\) 的大小。
- 区间长度较短时暴力做转移,常数同样会小很多。

浙公网安备 33010602011771号