生成函数练习记录&题解

生成函数练习记录

前言

最近把nflsoj上的题都贺完了,之前既定要补的题也已完成,算是步入小康,终于有了点自己可以支配的时间了。

这篇markdown中会记录我这段时光写过的组合计数题目,大概都会与生成函数相关。

题目没有按照难度排序。

题目会给多个链接,用以照顾对OJ有不同口味的人士。

题目记录均会在通过题目后开始撰写,因此无法保证完全按照思考过程来,但正确性和逻辑性会比较好。

很可能有typo,有细节的纰漏亦可指出。

[HEOI2016/TJOI2016] 求和 洛谷 / LOJ

直接给出 \(\Theta(n)\) 做法

\[\begin{aligned} Answer&=\sum_{i=0}^n\sum_{j=0}^n {n \brace k } \cdot 2^j \cdot j! \\&=\sum_{i=0}^n\sum_{j=0}^n\sum_{k=0}^j \cdot 2^j \cdot k^i \cdot \binom{j}{k} \cdot (-1)^{j-k} \\&=\sum_{k=0}^n( \sum_{i=0}^nk^i) \cdot \sum_{j=k}^n2^j \cdot (-1)^{j-k} \cdot \binom{j}{k} \\&=\sum_{k=0}^n( \sum_{i=0}^nk^i) \cdot [x^j](\dfrac{1-(2(x-1))^{n+1}}{1-2(x-1)}) \end{aligned} \]

先把 \(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\) 不会用到复合逆的其他性质,只是在中间结果中借用它的存在。

然后大力化简,过程如下:

\[\begin{aligned} F(x)&=x \cdot e^{H(x)-F(x)+F(x) \cdot p0} \\F(x)&=H(x) \cdot e^{F(x)\cdot (p0-1)} \\设p&=p0-1, \\F(x)&=H(x) \cdot e^{F(x)p} \\H^{-1}(F(x)p) \cdot F(x)&=(H^{-1}(F(x)p) \cdot e^{F(x)p}) \cdot H(x) \\H^{-1}(F(x)p) \cdot F(x)&=F(x)p \cdot H(x) \\H^{-1}(F(x)p)&=H(x)p \\F(x)&=\dfrac{H(H(x)p)}{p} \end{aligned} \]

P.S. 通过 \(H(x)=xe^{H(x)}\) 可以把 \(exp\) 给去掉

然后我们要求这个式子的第 \(n\) 项。

\[\begin{aligned} Answer &= [x^n] \dfrac{H(H(x)p)}{p} \\&=[x^n]\dfrac{1}{p}\sum_{i\geq 1} \dfrac{i^{i-1}}{i!}(H(x)p)^i \\&=\sum_{i\geq 1} \dfrac{(ip)^{i-1}}{i!}[x^n]H(x)^i \end{aligned} \]

后面那个式子的组合意义是 \(n\) 个点组成 \(i\) 个有根树的方案数乘 \(\dfrac{i!}{n!}\),除 \(n!\) 是因为egf,乘 \(i!\) 是因为选有根树是不讲究顺序的。

那么 \(n\) 个点组成 \(i\) 个有标号有根树,根据 \(\texttt{generalized Cayley's formula}\),直接得到方案数是 \(i\binom{n}{i}n^{n-i-1}\)

把这个结论带回去,计算完毕。

\[\begin{aligned} Answer &=\sum_{i\geq 1} \dfrac{(ip)^{i-1}}{i!}[x^n]H(x)^i \\&=\sum_{i\geq 1} \dfrac{(ip)^{i-1}}{i!}i\binom{n}{i}n^{n-i-1} \end{aligned} \]

[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 的定义和题面中的一样。然后写出生成函数的式子。

\[\begin{aligned} G_i(x)&=(S_{i+d_i}(x) \cdot x+1) \cdot f_i \\S_{i+1}(x)-S_i(x)&=(S_{i+d_i}(x) \cdot x+1) \cdot f_i \end{aligned} \]

这里会出现一个常数,比较丑陋,还会影响我们后期使用矩阵乘法时矩阵的大小,因此我们希望去掉它。这个常数产生的原因是最后一行的每个数都有一个初始贡献,我们可以在最后一行后面额外增加一行,然后强制要求终点是最后一行的第一个格子。

\[\begin{aligned} S_{i+1}(x)-S_i(x)&=S_{i+d_i}(x) x f_i \\S_i(x)&=S_{i+1}(x)-S_{i+d_i}(x) x f_i \end{aligned} \]

可以看出,当 \(d_i\) 非零时,这是一个项数很小的从右向左的递推式,因此转移可以写成矩阵的形式,同时矩阵中每个元素都是个次数较小的多项式,因此我们可以直接分治把这些矩阵乘起来。

\(d_i=0\) 时,直接从左向右暴力即可。

现在虽然我们不知道转移的初项 \(S_m(x)\) ,但是我们知道转移的末项,因此直接列出方程,求逆就能解出 \(S_m(x)\)

答案即为 \([x^n]S_m(x)\)

几点关于常数的事实:

  1. 矩阵乘法时先把矩阵所有元素 dft,乘完之后再 dft 回去,常数会乘上 \(1/3\)
  2. \(d_i = 2\) 时,矩阵大小是 \(3 \times 3\) 的,但可以发现多项式的长度只有区间长度的 \(1/3\)。 而 \(d_i = 1\) 时,实际上可以把矩阵写成 \(2 \times 2\) 的大小。
  3. 区间长度较短时暴力做转移,常数同样会小很多。
posted @ 2022-02-18 22:24  MarkizeKing  阅读(402)  评论(6)    收藏  举报