多项式总结
总结自 FSZ 的讲课。
多项式卷积
复数
定义复数 \(z\) 的表示形式为 \(a + bi\),\(i\) 为虚数单位。
那么基本运算法则是:
- \((a + bi) + (c + di) = (a + c) + (b + d)i\)。
- \((a + bi)(c + di) = (ac - bd) + (ad + bc)i\),同时在复数平面上考虑的话,将 \((a, b)\) 刻画为向量,那么有两者相乘,模长相乘,幅角相加。
单位根
根据代数基本定理,在复数域下,\(x^n = 1(n \ge 1)\) 这个方程有恰好 \(n\) 个不同的解,我们称其解为单位根。另外一个事实是,\(n\) 个单位根都落在单位圆上,原因显然(经过 \(n\) 次相乘,模长始终为 \(1\)),刻画出来的形式为 \(n\) 个单位根将单位圆均分为 \(n\) 块,不妨按照幅角大小依次从小到大定义为 \(\omega_n^0, \omega_n^1, ..., \omega_n^{n - 1}\)。
根据三角函数的定义可以得知 \(\omega_n = \cos \frac{2 \pi}{n} + i \cdot \frac{2 \pi}{n}\),\(\omega_n\) 可以看作单位根之间的间隔量。
DFT
我们通常定义的是一个 \(n - 1\) 次多项式 \(F(x)\),系数我就不写了。
多项式卷积就是求两个 \(n - 1\) 次多项式 \(F(x), G(x)\) 相乘的结果 \(H(x)\),暴力计算是 \(O(n^2)\),而我们力求优化这个过程。
根据基础常识和基本定理,\(F(x)\) 可以用 \(n\) 个不同点值唯一表示出来,比方说,通过两个不同的点我一定能够确定一条直线,通过三个不同的点我一定能够确定一个二次函数,以此类推。
我们希望的计算过程是,将 \(F(x), G(x)\) 全部化为点值后,对应点值相乘得到的结果最后再还原回 \(H(x)\),由于点值可以随便带入,我们不妨将 \(n\) 个单位根带进去计算,而 DFT 就是快速将单位根对应点值计算出来的过程。
为了方便计算下面的过程,我们先把 \(n\) 补齐为 \(2\) 的次幂。
不妨将 \(F(x)\) 表示出来:
将其奇偶分类定义多项式:
不难得到:
我们明确以下有关单位根的事实(\(n\) 为偶数):
将 \(\omega_n^i, \omega_n^{i + \frac{n}{2}}\) 分别带入上述关于 \(F(x)\) 的表达式有:
单位根的逆天之处此时就开始显现了,分治去做这个事情,可以做到 \(O(n \log n)\) 的时间求出 \(\omega_w^0, \omega_n^1, ..., \omega_n^{n - 1}\) 所对应的点值。
但问题是如何将相乘所对应的点值转化回去。
IDFT
这就是将所得点值逆回去的。
不妨设 \(f'_i = F(\omega_n^i)\),有一个结论是:
- 将单位根变成从幅角从大到小排序(\(1\) 仍然还是 \(\omega_n^0\)),将 \(F'(x)\) 带入去做 DFT,那么得到的结果除以 \(n\),便是原来的系数。
我们称这一步结论所进行的操作为 IDFT,即逆变换,于是多项式卷积就能在 \(O(n \log n)\) 的时间内解决。
NTT
DFT 和 IDFT 合起来我们一般称为 FFT,由于涉及单位根和三角函数,误差不是一般的大,但是科学家又已经证明在复数域下单位根是唯一具有这种快速计算性质的值,所以我们将视角转换,通常一般题目会加上取模的条件,那么在取模意义下,我们用原根来替换单位根。
你不太需要知道原根的定义,在 \(\mathbb F_{p}\) 下,我们定义关于 \(p\) 的原根为 \(g\),那么原根有如下类似单位根的性质:
- 假设 \(n | p - 1\),有 \(g^{\frac{p - 1}{n}}\) 的 \(n\) 次方 \(\mod p\) 的结果为 \(1\),且其 \(0 \sim n - 1\) 次方 \(\mod p\) 的值不等。
这一点就说明了其能够替代单位根,并且幂也满足其共轭和放缩的性质。
由于需要 \(n | p - 1\),所以通常 \(p - 1\) 都是一个 \(2\) 的很大次项的次幂乘上一些数的结果,需要记住的就只有 \(p = 998244353 = 7 \times 17 \times 2^{23} + 1\) 时,\(g = 3\)。
任意模数 NTT
这里不基于其他的性质,用 CRT 暴力合并三个模数意义下的 NTT 结果即可。
常数较大,比较罕见。
多项式操作
多项式求逆
给定一个 \(n - 1\) 次多项式 \(F(x)\),要求计算 \(\frac{1}{F(x)} \bmod {x^n}\) 所对应的多项式。
显然从低次项到高次项有一个暴力的 \(O(n^2)\) 做法,这里介绍一个最常用的倍增做法,下述的 \(\frac{n}{2}\) 皆为向上取整。
假设我们已经求得 \(G'(x)\) 满足:
需要求 \(G(x)\) 使得:
推一下式子:
显然此时就有:
递归卷积求解即可,根据主定理分析复杂度为 \(O(n \log n)\)。
牛顿迭代
先要知道泰勒展开和麦克劳林级数是什么东西。
泰勒展开
对于一个光滑连续函数(暂且先这么定义,限制严一点也没啥事)\(f(x)\) 和任意实数 \(a\),有:
你也能将 \(f(x)\) 就理解为一个多项式 \(F(x)\),本质一样,上述形式称为 \(f(x)\) 在 \(a\) 处的泰勒展开。并非对于所有 \(f(x)\) 定义域内的 \(x\),上述等式都成立,只是对于多项式的系数关系能用上述等式展开。
麦克劳林级数
通常对于一个光滑连续函数 \(f(x)\),在 \(0\) 处的泰勒级数被称为麦克劳林级数,给一些常见的生成函数中的麦克劳林级数就理解了:
很明显,其就是生成函数封闭形式的逆等式,和封闭形式本质上是一个东西。
由于这一部分并非很重要,这里就不列举更多的例子,要用的式子下面也会说。
这里的牛顿迭代指的是在多项式中的算法,不是那个求近似解的算法。
需要解决的问题是给定多项式 \(G(x)\),需要你求得 \(F(x)\) 使得 \(G(F(x)) \equiv 0 \pmod {x^n}\)。
还是一样的,假设现在已经求出 \(F_0(x)\) 满足:
比较牛逼的一件事是,将 \(G(F(x))\) 关于 \(F\) 在 \(F_0\) 处泰勒展开,你可以理解为将对应的结构带入,得到:
因为可以推出 \(F(x) \equiv F_0(x) \pmod {x^n}\),所以当 \(i \ge 2\) 时后面的项全部为 \(0\),得到:
显然有:
复合的话由于两个都知道就随便算算就行了,也可以将 \(x\) 不理解成指示元,理解成具体的数值,这样也许会更符合直觉。一般 \(G(x)\) 会是一个少项式,将项数理解为常数的话,递归写个求逆和卷积复杂度为 \(O(n \log n)\)。
为什么牛顿迭代会如此强势,因为在推导过程中,右侧的 \(0\) 完全没有对运算提供实质上的帮助,也就是说,将 \(0\) 更换为任意一个多项式该问题仍然可做,牛顿迭代需要 \(G(F(x))\) 无限可微,但一般题目都满足这个条件,所以不管。
多项式开方
问题是给定 \(H(x)\),求 \(F(x)\) 使得满足 \(F(x)^2 \equiv H(x) \pmod {x^n}\)。
构造关于 \(F(x)\) 的函数 \(G(F(x)) = F(x)^2 - H(x)\),那么如果一个 \(F(x)\) 满足 \(G(F(x)) \equiv 0 \pmod {x^n}\),就必定满足上述表达式了,就是我们需要求解的 \(F(x)\) 了。
用更加人性化的语言解释,设 \(G(x) = x^2 - H(x)\),将 \(x\) 当作函数变量,\(H(x)\) 当成一整个多项式去理解,那么现在需要求出满足 \(G(F(x)) \equiv 0 \pmod {x^n}\) 的 \(F(x)\) 就可以了,这完全是牛顿迭代的内容,套用即可。
多项式 exp
对于多项式 \(F(x)\) 来说,\(\exp F(x) = e^{F(x)}\)。
欸,那指数上是一个多项式是啥意思呢,基于麦克劳林级数,我们有如下等式:
那么就有了 \(\exp F(x)\) 的具体形式:
你敢信这东西竟然是收敛的?
其实很好理解,当 \(n \to + \infty\),\(n!\) 的量级此时显然会比 \(eps^n\) 的量级要大的多,自然就收敛了。
问题是给定多项式 \(H(x)\),现在要求 \(F(x) \equiv \exp H(x) \pmod {x^n}\)。
推一下式子:
我们假设求 \(\ln F(x)\) 是好求的,那么现在只需要构造 \(G(F(x)) = H(x) - \ln F(x)\) 去做牛顿迭代就好了。
多项式 ln
下面来解释一下上述好求的到底是如何求的。
这里同样给出基于麦克劳林级数的对于 \(\ln x\) 的定义:
问题是给定多项式 \(H(x)\),现在要求 \(F(x) \equiv \ln H(x) \pmod {x^n}\)。
有定理:当且仅当 \([x^0]F(x) = 1\) 时,\(\ln F(x)\) 有意义/才有 \(\ln F(x)\)。
固定了 \(0\) 次项,思路就很自然了。考虑先将 \(\ln F(x)\) 求导,然后使用求逆将导数求出来,最后再积分回去即可,常数项是好处理的。
多项式取模
问题是给定 \(F(x), G(x)\),要求 \(Q(x), R(x)\),使得 \(F(x) = Q(x)G(x) + R(x)\),其中 \(F(x)\) 的次数为 \(n\) 次,\(G(x)\) 为 \(m\) 次多项式,由于 \(R(x)\) 是余数所以视作 \(m - 1\) 次。
思考以往的 \(\mod x^n\) 都是将 \(x\) 的 \(n\) 次项以后的项全部忽略,这里则不一样,则是将 \(x\) 的 \(m\) 次项之前的项全部忽略,不妨考虑相似的处理方式。
考虑定义一个关于 \(F(x)\) 的系数翻转操作:
显然,将等式两边多项式系数翻转(将次数视作相等)后等式仍然成立:
乘上 \(x^{n - m + 1}\) 是为了对齐次数。接下来我们简化一下:
显然有:
使用多项式求逆解出 \(Q^R(x)\) 后再卷积减法一下即可得到 \(R^R(x)\) 的值了,然后再翻转回去即可。
Extra:常系数齐次线性递推
基本就是知道了一个数列前 \(k\) 项 \(a_0, a_1, ..., a_{k - 1}\),已知:
要求快速递推出第 \(n\) 项,\(n \le 10^9\)。
这里有一个很简单的 \(O(k^3 \log n)\) 的矩阵快速幂做法,也有一个基于 Kitamasa 算法的 \(O(k^2 \log n)\) 做法,这里介绍一种更优的做法。
考虑 Kitamasa 算法的过程,其中很重要的一点是,将计算转化为分配到 \(a_0, a_1, ..., a_{k - 1}\) 上的系数,只要我们能够快速计算出每一项的系数,我们就胜利了。
用多项式的语言描述,就是需要计算将 \(x^n\) 对于这个递推的特征多项式不断取模后的结果。
等等,特征多项式是什么?
特征多项式
利用上述表示符号,那么特征多项式 \(F(x)\) 的定义为:
我们不太需要知道其定义方法是什么样的。
可以理解,将 \(x^n\) 对特征多项式取模,相当于逐个消掉最高次项,转化为低次项的结果,本质上就是在做我们那个过程的转化,至于为什么是减号,这是因为在取模过程中我们是在不断的做减法,对冲一下就好了。
那么套个多项式取模的模板即可,由于 \(n\) 很大,我们需要在计算 \(x^n\) 的时候写个快速幂就好了。
时间复杂度 \(O(k \log k \log n)\)。
分治 FFT
通常指一种思想,但是模板题给的问题是:
- 给定序列 \(f_1, ..., f_n\),求 \(g_1, ..., g_n\),满足 \(g_i = \sum_{j = 1}^i f_j g_{i - j}\),边界有 \(g_0 = 1\)。
设计一个分治函数 \(h(l, r)\),我们的目标是解决 \(g_l, ..., g_r\) 的值,首先我们可以调用 \(h(l, mid)\) 解决左半部分的 \(g\),不难发现左半部分对右半部分的贡献形如一个卷积形式,调用一下 FFT/NTT 即可,因为每一层总复杂度都是 \(O(n \log n)\),所以总复杂度为 \(O(n \log^2 n)\)。
常数有点大,但是解决的问题明显更广泛。
Chirp-Z 变换
Chirp-Z 变换是为了应对快速对于多项式 \(F(x)\) 和任意一个非负整数 \(c\) 以及一个次数 \(m\),计算出 \(F(1), F(c^1), ..., F(c^{m - 1})\),我们此时就是要计算:
有一个关键也非人的观察是:
带入原式:
显然将 \(c^{\binom{i + j}{2}}\) 倒一下就变成了卷积的形式,NTT 即可。
这个做法的高明之处到底在哪?
同样有 \(ij = \frac{(i + j)^2 - i^2 - j^2}{2}\),为什么我不用这个?
因为代入之后指数可能不为整数,在模意义下可能不存在二次剩余,这个做法的高明之处就在于拆成了相对独立的系数,并且满足指数都是整数。
单位根反演
在复数域内,有单位根反演:
这一理论完美刻画了整除关系的计数方式,也有扩展:
其中 \(F\) 为一个 \(m\) 次多项式,\(f\) 就是系数。
但你知道,复数域内我们一般不喜欢做什么操作,但是通常在 \(\mathbb F_p\) 意义下,该公式就变得十分重要,此时将单位根 \(\omega_n\) 变为原根 \(g^{\frac{p - 1}{n}}\) 即可,这下这个公式就变得没有精度损失和能看懂了。
题目
P4841 [集训队作业2013] 城市规划
设 \(F(x)\) 为连通图的方案数,\(G(x)\) 为简单图的方案数,显然 \(G(x)\) 是好求的,根据生成函数一些运算的意义,有:
\(i = 0\) 的项一般不特殊考虑,因为 \([x^0]F(x) = 0\),能加进来就加进来,根据麦克劳林级数,有:
写个多项式求 ln 即可,一般在处理多项式连通图计数问题,求 ln 是一个很常用的手法。
CF438E The Child and Binary Tree
设一个指示函数 \(g_i\) 表示 \(i\) 是否在给定集合中,设 \(f_i\) 为点权为 \(i\) 符合条件的二叉树个数,那么可以写出转移:
其中 \(f_0 = 1\),容易发现后面一坨就是自己卷自己,将其作为系数写成对应的生成函数 \(F, G\) 有:
求得 \(F\) 为:
显然 \(F\) 必须是收敛的才行,所以取 \(F = \frac{1 - \sqrt{1 - 4G}}{2G}\)
多项式开根加求逆即可。
ps:请注意多项式求逆的条件是常数项非 \(0\),这种推导方法中间有问题,但结果是对的(你可以理解为一元二次方程的求解本质不依赖于求逆)。
AT_abc307_h [ABC307Ex] Marquee
展开之后就是 FFT 求字符串带通配符匹配的模板了。
CF1975G Zimpha Fan Club
首先匹配默认指带通配符匹配。
如果两个字符串都有 *,那么结论是中间的部分可以错开匹配,只需要比对前缀后缀即可,因此此时将情况转化为只有一个字符串有 * 的情况。
显然此时只需要按照 * 将串中其它部分分隔开来,然后要求每一段在另一个串中都要按顺序匹配上,所以直接做就是 \(O(mn\log n)\) 的了。
考虑对于目前子串 \(s\),截取目前一段长度为 \(2|s| - 1\) 的长度的文本串进行匹配,如果没有匹配上就令你的匹配左端点 \(+ |s|\),显然正确,最后最坏就是将整个串都多遍历一遍,复杂度优化为 \(O(n \log n)\)。
P3723 [AHOI2017/HNOI2017] 礼物
题意是给定序列 \(a, b\),可以循环移位 \(b\),选择整数 \(c\),求 \(\sum_{i = 1}^{n}(a_i - b_i + c)^2\) 的最小值。
考虑化简:
摒弃固定的东西(包括那个关于 \(c\) 的二次函数),我们需要求的东西就是:
那么显然将 \(b\) 断环成链后将 \(a\) 翻转,这东西答案就是一个卷积之后对每个位置求 \(\max\)。
CF553E Kyoya and Train
考虑设计一个期望意义下的 DP,设 \(f_{i, j}\) 为到达点 \(i\),花费时间为 \(j\),最优情况下的最小花费是多少,考虑转移:
显然这个转移成立,因为 \(j\) 只会减小。
其中 \(dis\) 函数考虑 \(O(n^3)\) 求解,而第二步的转移可以分治 FFT 解决,每次都相当于一个卷积的形式,总时间复杂度就是 \(O(mt \log^2 t + n^3)\)。
AT_agc005_f [AGC005F] Many Easy Problems
考虑计算每个点对于答案的贡献,就是每个点在答案中被统计了多少次。
使用容斥,包含某个点的方案数不好计算,那么不包含的方案数就很好计算了,要么所有点都在其某一个儿子的子树中,要么都不这个点的子树中,根据这一点,对于固定的 \(k\),我们很容易算出一个点的贡献,具体来说为:
仍然摊到每个点的计算上,发现后面的求和本质上对于每个点只会计算一次,不难计算出 \(k\) 的答案 \(ans(k)\):
后面的项转化为枚举 \(siz_i\) 的值之后可以变成一个有关于差卷积的形式,使用 NTT 即可,在原根的选择上需要使用一些手法解决。
CF755G PolandBall and Many Other Balls
有一种小巧思的做法。
正常做法是序列上 DP,很容易设出 \(f_{i, j}\) 表示前 \(i\) 个数分为 \(j\) 组的方案数,但是这样转移无论如何都是 \(O(nk)\) 的。
但是你要知道,我们的转移不仅可以 \(i \to i + 1\),还可以 \(i \to 2i\),此时转移就是将 \(f_{i, j_1}\) 和 \(f_{i, j_2}\) 和在一起,或者让 \(f_{i - 1, j_1}\) 和 \(f_{i - 1, j_2}\) 合并在一起,中间两个数视为一组,这促使我们往倍增的角度思考(其实仔细想想就会知道 fbnq 也有一个倍增式)。这种 trick 叫做倍增 FFT trick。
写成生成函数,那么就有以下转移:
这样得到了我们完备的转移规则,类似倍增不样不断二进制扩展即可,时间复杂度 \(O(k \log k \log n)\)。
LOJ6485
答案形式为:
单位根反演:
二项式定理:
其他的 \(a_1, a_2, a_3\) 都是这么算的,不过单位根上加了一个偏移量。
P6295 有标号 DAG 计数
根据连通图计数的技巧,我们知道先忽略弱联通限制,最后求一遍多项式求 ln 即可得到弱连通图个数了。
考虑 DAG 容斥经典手法,枚举入度为 \(0\) 的部分,设 \(f_i\) 为 \(i\) 个点的有标号 DAG 个数,那么转移:
根据 Chirp-Z 变换的 trick,得到;
拆成多项式乘积即可解得 \(f\),最后做一边多项式求 \(\ln\) 即可。
符号化方法
这一部分内容是为了规范我们的思考过程,将灵机一动转化为公式化方法。
无标号组合类和 OGF
一个组合类是一个可数集合 \(\mathcal A\),内部包含了一些组合对象,比如说需要计数的序列,数之类的,由于是无标号组合类,所以所计数的内容应该是无标号的,所以一般不对序列这种固定死结构的东西计数。
对每个组合对象可以构造一个大小函数进行映射,比如说树的大小,环的颜色数等等(当然也可以不这么定义),对于非负整数 \(n\),记录 \(A_n = |\{x | x \in \mathcal A, |x| = n\}|\)。
OGF,意为普通型生成函数,一个形式幂级数,下面定义:
容易发现 \([x^n]A(x) = A_n\)。
基础的组合类 \(\mathcal{E, Z}\) 的 OGF 记为:
因为常数项无法转化为非常数项,非常数项也无法转化为常数项,所以需要有两个。
笛卡尔积
定义该运算的形式为 \(\mathcal C = \mathcal A \times \mathcal B\),其中 \(\mathcal C\) 将两个组合类中的元素组合起来当成一个有序对处理,有:
而对于大小的定义也是严格的:
对于 OGF 来说仍然是相乘的关系 \(C(x) = A(x)B(x)\)。
无交的并
如果有交的话大小函数会出现一些奇奇怪怪的问题。
记该运算为 \(\mathcal C = \mathcal A \cup \mathcal B\),大小函数不变,则组合对象就是原本的两个组合类中的对象放在一起,互不相同,没有冲突,此时有 \(C(x) = A(x) + B(x)\)。
加法
定义 \(\mathcal A + \mathcal B = (\mathcal E_1 \times \mathcal A) \cup (\mathcal E_2 \times \mathcal B)\),其中 \(\mathcal {E_1, E_2}\) 分别是关于 \(\mathcal{A, B}\) 的基础组合类(组合对象不一样)。
构成一个有序对就很好解决了有交的问题了。
Sequence / SEQ 构造
为什么需要构造,因为这有助于我们刻画题目中的一些计数结构。
SEQ 构造生成所有可能的有序组合,其基于一个组合类,举个例子是:
构造出来的是一个大小为无限的组合类,但是在解决问题中我们只关心前面有限项。
对应的 OGF 才是重中之重,根据简单的推导,有等式:
看这形式你就知道我什么我们要取“无限”这个定义了。
Multiset / MSET 构造
MSET 构造生成所有的无序组合(取 Multiset 之意是指可重),具体形式就不写了,具体来说就是 \((\alpha, \beta)\) 和 \((\beta, \alpha)\) 视作同一种元素,不计算顺序。
对应的 OGF:
我们称这个操作为 Pólya Exp,写作 \(\text{Exp}(A(x))\)。
Powerset / PSET 构造
PSET 构造生成所有的子集,字面意思就是取所有子集,这里构造出来的组合类大小是有限的了,经过一些并不简单的推导可以得到其 OGF 为:
Cycle / CYC 构造
CYC 构造生成所有可能的组合,不区分轮换不同的组合,比如说 \((\alpha, \beta, \gamma)\) 和 \((\gamma, \alpha, \beta)\) 属于同一组合对象,除了这一点之外与 SEQ 构造是没有区别的。
其对应的 OGF 可以用比较困难的方法推出来为:
我们称这个操作为 Pólya Log,写作 \(\text{Log}(A(x))\)。
有标号组合类和 EGF
其实组合类的定义比较一样,只不过把不区分标号作为等价标准变成区分标号作为等价标准。此时一个组合对象的大小一般就是同结构下标号个数。
EGF 则为指数型生成函数,同样也是一个形式幂级数,形式如下:
容易发现 \([\frac{x^n}{n!}]A(x) = A_n\)。
无交并
同无标号组合类。
加法
同无标号组合类。
笛卡尔积
由于有标号,所以过程中需要乘上组合数系数,但是因为与阶乘相抵消了一下,所以此时仍然有:
Sequence / SEQ 构造
因为定义没有变化,相同元素仍然区分标号,但是又因为有阶乘的缘故,所以 EGF 表达形式仍然有:
Multiset / MSET 构造
MSET 构造生成所有的无序有标号序列,不区分组合对象的顺序,解释来说,对于一张图的若干个连通块,我们不区分其排列顺序,但是如果换了一个标号,我们仍然认为它不同。
其实 EGF 的形式非常好写:
Cycle / CYC 构造
可以通过标号来区分元素,因此一个长度为 \(k\) 的环先转 \(k\) 次必定得到 \(k\) 个会被记重的结构,贡献就是 \(\frac{1}{k}\),有 EGF 表示:
Pointing / PNT 构造
PNT 构造的意思是在一个组合对象大小种结构一样,标号不同的元素中选择一个关键元素比如说给树定根,对应的 EGF 为(不怎么常用应该):
PGF
这一部分不属于符号化方法的内容(因为没有符号化方法,或者是有但是我不知道)。
以 P4548 [CTSC2006] 歌唱王国 为例,总结一些有关于 PGF 的应用技巧。
考虑刻画两个结构,在随机结束的情况下,设 \(f_i\) 为此时长度恰为 \(i\) 且结束时的概率,\(g_i\) 为此时长度为 \(i\) 且之前都没有结束过的概率(重要理解,随机结束但是目前只考虑到 \(i\),这在接下来的步骤中非常重要),不妨对这两个东西构造 PGF \(F(x), G(x)\)。这里利用 \(F(x)\) 来分享在 PGF 里一些好用的性质,不难发现此时 \(F(1) = 1\),这是因为此时的结果为所有情况概率的总和,\(F'(1) = E(X)\),代表这个事件的期望,求导之后对应概率恰好乘上了一个 \(i\),带入 \(1\) 将 \(x^{i - 1}\) 消掉就是期望。
我们知道一个简单的递推式是:\(g_i = f_{i + 1} + g_{i + 1}\),这是因为到 \(i\) 还没有的概率就是到 \(i + 1\) 还没有的概率加上恰到 \(i + 1\) 有的概率,由于 \(g_0 = 1\),写成方程就是:
容易解得:
刚刚说过 \(F'(1)\) 表示期望,两边求导:
带入 \(x = 1\):
此时求得 \(G(1)\) 即可,还需要列一个方程才能求得 \(G(1)\),构造一个强制能够满足结束条件的状态:\(G(x)(\frac{x}{n})^m\),具体意义为,目前到 \(i\) 还没有组成的概率乘上后面接上一个 \(s\) 的概率,这样必定结束(这一步不感性理解很容易绕进去,你可以认为概率是模糊的概念,有时可以理解为随机结束,有时可以理解为正在随机)。但是你会发现可能会提前结束,所以可以用 \(F(x)\) 推出这个东西,具体为 \(\sum_{i = 1}^m a_i F(x) (\frac{x}{n})^{m - i}\),其中 \(a_i\) 指示 \([1, i]\) 是否是 \(s\) 的 border。
带入 \(x = 1\),那么列出等式并化简:
由于 \(F(1) = 1\),所以:
于是这个题目做完了,这一类限制比较弱的第一次结束类问题都能依靠这个 trick 解决,当然像 ARC136F 这种题我就不知道是咋想出来的。
https://www.cnblogs.com/HenryHuang-Never-Settle/p/14702997.html
DGF
有关于数论的生成函数,称为 Dirichlet 生成函数。
设一个数论函数 \(f\),一般令其在 \(i\) 处的点值表示为 \(f_i\),构造 DGF 为:
如果 \(f\) 是积性函数,那么根据唯一分解,可以拆分成若干个质数相乘,这在下面的数论函数 DGF 推导中非常有用:
为什么下面是 \(i^x\),熟悉黎曼函数的人可能会知道,对于单位函数 \(1(n) = 1\),它的 DGF 表示形式:
但是在这里,\(\zeta(x)\) 更多的是作为中间量,向我们揭示不同数论函数之间的关系。除了定义式,我们需要另外一个形式来表示 \(\zeta(x)\),就是上面说的质数分解:
DGF 的乘法
考虑两个数论函数 \(f, g\),其 DGF 分别为 \(F(x), G(x)\),那么按照多项式的乘法规则有:
所以两个数论函数的 Dirichlet 乘法的结果的 DGF 就相当于这两个数论函数的 DGF 的多项式乘法,因此 \(f * g \to F(x)G(x)\)。
单位函数 \(\epsilon\)
显然其 DGF 为 \(1\)
常数函数 \(1\)
上面推导过了 DGF 就是 \(\zeta (x)\)。
莫比乌斯函数 \(\mu\)
考虑 \(\mu\) 的定义是,如果唯一分解有一项的指数大于 \(1\),那么为 \(0\),否则是分解出来的质数个数个 \(-1\) 相乘,根据定义,列出 DGF(从质数合成的角度出发):
先在你或许理解为什么要将 \(\zeta\) 变成这个形式作为中间量了。
恒等函数 \(\text{id}_k\)
恒等函数的定义是 \(\text{id}_k(n) = n^k\),那么有:
欧拉函数 \(\varphi\)
考虑欧拉函数 \(\varphi(n)\) 的定义式,假设 \(n = p_1^{k_1} p_2^{k_2} ... p_e^{k_e}\),那么有:
还是将 DGF 拆成质数分解:
中间省略了一些计算过程。
除数函数 \(\sigma_k\)
除数函数的定义是 \(\sigma_k(n) = \sum_{d | n} d^k\),这个东西也是积性函数,类似上面的推法(欧拉函数一部分),可得 DGF:
DGF 一个非常关键的性质是:它可以推导出不同数论函数之间的转化关系,比如:$$\varphi * 1 = \text{id} \to \frac{\zeta(x - 1)}{\zeta(x)} \times \zeta (x) = \zeta (x - 1)$$
我们就不需要记得那么多转化式,只需要记注对应的 DGF 就好了!而且 DGF 忘记了也可以现推。
DGF 的除法
有数论函数 \(f, g\),需要求一个 \(h\) 使得:
比较有趣的是,多项式的除法也是这么定义的,在定义这种逆运算时,一般不会直接定义,而是通过其正运算表示出来。推一下具体的项:
求解出 \(h_i\) 向倍数转移贡献即可,形式和杜教筛其实差不多。
题目
LOJ6268 分拆数
套用 MSET 构造,发现令 \(F(x) = x^1 + x^2 + ... = \frac{x}{1 - x}\),那么答案多项式 \(G(x)\) 为:
了解一下咋求这东西,则带入得到(本质只考虑前 \(n\) 项的话):
显然一共需要计算的项只有 \(O(n \log n)\) 项,最后带回去做一遍 \(\exp\) 即可。
P4389 付公主的背包
也是 MSET 构造模板题,将每个 \(i\) 更换为 \(v_i\) 即可。
CF2174F Mosaic Tree
转化到 Prufer 序列上考虑,一个点的度数就是在其上出现次数 \(+ 1\),考虑如果知道了度数序列 \(d\),那么答案就是一个多重组合数。不妨一个颜色一个颜色的考虑,对于每个颜色,我们不仅要决策其到底用了哪些点(这一部分题目已经给你),还要决策这些总度数到底如何分配,不妨假设用了 \(t\) 个点,度数总和为 \(s\),那么对应其贡献为:
可以推导至:
可以看作 \(\exp\) 为表示形式,代替了那一托东西,却有实际上的算术意义。
此时对于不同奇偶性个数的颜色来说,\(s - t\) 会取遍所有奇数或者偶数(因为 \(t\) 固定,\(s\) 的奇偶性固定),但是在后面组合颜色的过程中,我们不好判定每个颜色到底是奇数还是偶数的 \(s - t\),不妨此时将奇偶性与 \(s - t\) 不一样的系数位置直接变为 \(0\),根据一些数学知识可以得到,此时该种颜色的生成函数为 \(\frac{e^{xt} \pm e^{-xt}}{2}\)。
考虑此时将 \(c\) 种颜色的生成函数全部乘起来,在之前的步骤里我们已经讨论过奇偶性的问题,所以此时只需要满足 \(s - t\) 的总和为 \(n - 2\) 即可。需要注意的是,此时所有生成函数乘起来最后的结果都是 \(e^{xi}\) 的形式(显然 \(i > n\) 或者 \(i < -n\) 就没有意义了,舍弃即可),可以通过背包将 \(e^{xi}\) 的系数求出来,这样就得到了最终的形式,设 \(e^{xi}\) 的系数为 \(c_i\),则答案为:
展开一下 \(e\) 的具体形式可以得到:
别忘了这是 EGF,最后需要乘上一个 \((n - 2)!\),因此答案就是:
直接做即可。
UOJ 450
显然,\(d = 1\) 答案就是 \(k^n\)。
对于 \(d = 2\),考虑生成函数,答案就是 \([\frac{x^n}{n!}]\left(\sum_{i = 0}^{+ \infty} \frac{x^{2i}}{(2i)!}\right)^k\),利用一些封闭形式转化手段和上一题去除奇数次项系数的技巧,得到其等价于:
利用二项式定理,得到:
那么我们就是要求 \(e^{2i - k}\) 的 \(n\) 次项系数除以 \(n!\),展开一下就得到 \((2i - k)!\),所以答案就是:
OK,我们现在只需要解决 \(d = 3\) 就好了,在下面的推导中,你会意识到 \(d = 2\) 时 \(-1\) 的系数和 \(1\) 的系数是一次单位根和二次单位根,\(d = 3\) 其实就是拓展成三次单位根了。
考虑 \(d = 3\) 的生成函数,答案为:
我们此时无法利用直觉将不是三的倍数次项给变为 \(0\),如果是 \(d = 2\) 那么生成函数就是 \((\frac{e^x + e^{-x}}{2})^k\),考虑 \(d = 3\) 怎么推导。
使用单位根反演,原本的形式变为:
反演一下可得最终形式是:
三项式展开即可。
这种有关于整除类题目都可以往单位根反演的角度思考。
P7364 有标号二分图计数
设 \(n\) 个点的连通二分图生成函数为 \(F(x)\),\(n\) 个点的二分图生成函数为 \(G(x)\),在本题中 \(G(x)\) 不好求,我们使用 \(F(x)\) 表示出来:
考虑先给二分图染色,染色完的二分图计数设为 \(H(x)\),则系数 \(h_n\) 可以简单表示出来:
仍然利用 \(ij\) 的组合数拆分形式,这一块可以用卷积 \(O(n \log n)\) 求出来。
如果给 \(G(x)\) 组合一下,那么每个连通块定一个标号即可反推出 \(H(x)\),有:
所以得到给 \(H(x)\) 开个根就是 \(G(x)\) 了。
P5828 边双连通图计数
考虑容斥,枚举割边边集 \(S\),此时剩下的部分一定是若干个连通块被这些边连成一个树的结构,假设连通块大小为 \(a_1, a_2, .., a_k\),根据 Prufer 序列的结论,贡献为:
容斥系数为 \((-1)^{k + 1}\),那么带入进去贡献变成:
有标号连通图的生成函数我们设为 \(F(x)\),那么设 \(G(x)_i = -niH(x)_i\),就是后面那一托的生成函数,那么答案就是 \([\frac{x^n}{n!}] - \frac{1}{n^2} e^{G(x)}\),具体原理和有标号连通图的求法一样。
P5900 无标号无根树计数
严格强于无标号有根树计数,所以我们先考虑无标号有根树怎么做。
考虑将根结点,剩下的部分构成形态,由于是无标号,不考虑顺序,那么写成生成函数类似于背包:
大概解释一下什么意思,\(x\) 是因为去除掉根结点需要移位,后面 \(k\) 是枚举子树大小,\(x^{ik}\) 是枚举有 \(i\) 个大小为 \(k\) 的子树属于同一类,\(F(x)_k\) 的次幂是要将这么多种大小为 \(k\) 的子树组合起来,因为无标号所以同种类不区分,因此才要干这么一出。
那么先把里面的求和化成封闭形式:
使用一些手段优化这个过程,遇到连乘应该有的思路是取 \(\ln\) 之后变成连加:
P5824 十二重计数法
组合计数最高的山,最长的河,最基础的基础。
- 球有标号,盒子有标号,无限制。
给每个球决定盒子,那么答案是 \(m^n\)。
- 球有标号,盒子有标号,盒子球数上限为 \(1\)。
每次放入一个球后,就会有一个盒子无法选择,符合下降幂定义,答案为 \(m^{\underline n}\)。
- 球有标号,盒子有标号,盒子球数下限为 \(1\)。
不妨转化角度,将 \(n\) 个球分成 \(m\) 个区分的组,组肯定不可能有空,由于盒子之间区分,根据第二类斯特林数定义,答案就是 \(m! {n \brace m}\)。
关于第二类斯特林数的求法,容斥有多少组为空,然后剩下的方案数是好算的,假设目前 \(i\) 个组钦定为空,那么容斥系数为 \((-1)^{i}\),需要关心一下标号的问题。
- 球有标号,盒子无标号,无限制。
考虑第二类斯特林数本来就是计算组不区分的方案数,那么答案应该就是 \(\sum_{i = 0}^m {n \brace i}\)。
可以将原本第二类斯特林数的式子化好看一点卷积算,就是第二类斯特林数-行。
- 球有标号,盒子无标号,盒子球数上限为 \(1\)。
如果 \(n > m\),那么答案为 \(0\),否则所有装入方案等价,答案为 \(1\)。
- 球有标号,盒子无标号,盒子球数下限为 \(1\)。
第二类斯特林数定义,答案为 \(n \brace m\)。
- 球无标号,盒子有标号,无限制。
由于球没有区分,盒子又有区分,所以我们只关心球的个数,考虑朴素插板法,由于可以插空,所以方案数为 \(\binom{n + m - 1}{m - 1}\),具体来说组合插板位置,然后给每一组里球的个数减一。
- 球无标号,盒子有标号,盒子球数上限为 \(1\)。
显然就是从 \(m\) 个盒子中选择 \(n\) 个来放球,答案为 \(\binom{m}{n}\)。
- 球无标号,盒子有标号,盒子球数下限为 \(1\)。
插板法,不过不要新添加球了,答案为 \(\binom{n - 1}{m - 1}\)。
- 球无标号,盒子无标号,无限制。
为了一盘醋包了一顿饺子。
将 \(n\) 划分成 \(m\) 个数不区分的自然数的方案数,和分拆数那个题很像,但是那个题没有固定拆分出来的数的个数 \(m\),并且本题是自然数。不能无脑套用 MSET 构造,考虑一种做法是,设 \(f_{i, j}\) 为 \(i\) 分成 \(j\) 个自然数的方案数,根据经典手法,转移为:
意为目前将所有数 \(+ 1\),或者在开头再加一个 \(0\),不难验证其正确性。
考虑给 \(f_{*, j}\) 设一个生成函数 \(F_j(x)\),根据 DP 转移:
直接展开成连乘形式:
连乘使用取 \(\ln\) 化成连加:
根据麦克劳林级数展开 \(\ln\):
显然根分拆数那个题一样,\(x^{ij}\) 最多只有 \(O(n \log n)\) 种组合方式,也就是说最多只需要计算 \(O(n \log n)\) 项(\(ij > n\) 显然就没有意义了),最后求个 \(\exp\) 即可得到 \(F_j(x)\)。
我们记这个答案为 \(p(n, m)\) 分拆数。
- 球无标号,盒子无标号,盒子球数上限为 \(1\)。
同样,当 \(n > m\) 答案为 \(0\),否则答案为 \(1\)。
- 球无标号,盒子无标号,盒子球数下限为 \(1\)。
还是一样的套路,将每一组先放 \(1\) 个球,那么答案就是 \(p(n - m, m)\)。
Extra:拉格朗日反演
有关于复合逆的一个反演形式。具体来说,有:
需要注意的是该反演的使用前提是 \(F, G\) 常数项应为 \(0\),且 \(1\) 次项系数应非 \(0\)。
顺便记录一下扩展拉格朗日反演,其描述内容是:
其中 \(F, G\) 的条件和上述一样,\(H\) 无特殊条件。
题目
集合幂级数
基础定义
类比通过序列构造形式幂级数,有时我们遇到有关二进制的子集题目同样也要刻画子集关系,这时就出现了集合幂级数。
通过一个长度为 \(2^n\) 的序列 \(f_0, f_1, ..., f_{2^n - 1}\) 来刻画子集信息,可以构造一个集合幂级数,同样也是一个 \(n\) 元多项式:
其中 \(p_j\) 代表二进制意义表示下集合 \(i\) 的第 \(j\) 位,你可以想象 \(x_0 \sim x_{n - 1}\) 就是用来控制所有子集二进制位信息的。
但是这样写不好助于我们理解,不妨将 \(x_0 \sim x_{n - 1}\) 压成一个元 \(x\),允许定义“集合”作为 \(x\) 的指数,也就是 \(x^i\),那么集合幂级数就被写成了更好看通用的形式:
这里不要将 \(S\) 当成具体的二进制数理解,而是要当成每个二进制位组合成的集合理解。
卷积
需要定义两个集合幂级数的乘法,第一步就是,对于两个指数为集合的 \(x^S, x^T\),如何定义乘法。
实际上,这一步通常是不确定的,根据题目要求定义乘法,根据 FMT/FWT,我们知道处理二进制的卷积方式对应的乘法一般有以下三种:
- 或卷积:\(x^S \times x^T = x^{S \cup T}\)。
- 与卷积:\(x^S \times x^T = x^{S \cap T}\)。
- 异或卷积:\(x^S \times x^T = x^{S \oplus T}\)。
根据一些知识,我们知道其都可以 \(O(n 2^n)\) 计算。同时还有一种子集卷积:
- 子集卷积:\(x^S \times x^T = x^{S \cup T} [S \cap T = \emptyset]\),类似于指数上做无交并运算。
复杂度稍微劣一点,可以 \(O(n^2 2^n)\) 计算。
这样就完成了两个集合幂级数 \(F(x), G(x)\) 的卷积定义,具体运算得分情况讲。
FMT
FMT 解决或卷积和与卷积。
具体而言定义集合幂级数 \(F(x), G(x)\),乘法运算为或/与运算,求 \(H(x) = F(x)G(x)\)。
考虑此时将集合当做一个二进制数,两边的系数当成序列,就有:
使用子集反演,此时需要只需要求解:
根据子集反演的结论:
继续推导,有:
后面使用高维前缀和即可做到 \(O(n 2^n)\)。
与卷积的情况,将 \(f, g\) 其中一个二进制取反后取超集进行反演,和或卷积就一样了只不过最后的子集高维前缀和变成了超集高维前缀和。
FWT
使用 FWT 同样也可以解决 FMT 问题,但是并不优美也大材小用,在异或卷积里我们无法用上述一样的方法做这个问题,需要一些更强劲的结构。
我们定义 \(x \circ y\) 表示 \(x|y\) 中 \(1\) 的个数的奇偶性,容易得到 \((x \circ y) \oplus (x \circ z) = x \circ (y \oplus z)\),相当于构造一个运算与异或有分配律。FWT 的核心是构造等价结构,注意到对于任意 \(0 \le i < 2^n\):
相当于将每个多项式 \(F, G, H\) 都构造成一个新的多项式 \(F', G', H'\),使得其满足可以直接卷积的性质,对于 \(F', G', H'\) 的求法可以魔改高维前缀和,剩下的部分就是完全一样了,最后再反演回去即可。时间复杂度 \(O(n 2^n)\)。
子集卷积
考虑如何描述 \(S \cap T = \emptyset\) 的限制,可以等价于 \(|S| + |T| = |S \cup T|\),不难想到给原本的卷积加上一维大小维 \(f_{i, j} = a_j[|j| = i]\),那么定义或卷积符号为 \(\cdot\),那么就是要求:
直接套用或卷积板子即可,时间复杂度 \(O(n^2 2^n)\)。
关于子集卷积,将集合幂级数用多元多项式的方式写出来,那么实质上 \(F(x_0 \sim x_{n - 1}) \cdot G(x_0 \sim x_{n - 1}) = F(x_0 \sim x_{n - 1})G(x_0 \sim x_{n - 1}) \bmod x_0^2 \bmod x_1^2 \bmod ... \bmod x_{n - 1}^2)\),其中 \(\cdot\) 指的是子集卷积运算,这种形式更加偏代数计算一点。
例子
首先就是 NOI 2025 D2T2 集合一题。
我们对于 \(2^n\) 个可能的选出来的数构造一个二元集合幂级数,构造过程和形式幂级数很像:
其中 \(a_S\) 显然就代表 \(S\) 这个集合所代表的数对应的值,这里的乘法相当于与卷积,显然每个 \(a_S\) 被选了也只会乘一次,因为题目中保证了 \(P, Q\) 不交的性质。答案就是所有 \([x^Sy^S]G(xy)\) 的和,在这里你可以将 \(S\) 当成数去想会更好理解一点。
以 CF53E Dead Ends 作为例子,再来描述一下集合幂级数的技巧。
考场上写不出来怎么办
有的时候没必要追求 \(O(n \log n)\) 的复杂度,做到 \(O(n \log^2 n )\) 就够了。
多项式求逆
这个感觉没啥必要写双 log,单 log 又不是难推。
多项式 exp
首先你得满足常数项为 \(0\),不然不收敛。
考察我们现在已知多项式 \(A(x)\),需要求解 \(B(x)\) 使得:
对两边求导:
由于已经确定常数项为 \(0\),两边再求积分得到:
不妨令 \(C(x) = A'(x) B(x)\),则:
拆开来看就是一个半在线卷积的形式,可以分治 FFT 做到 \(O(n \log^2 n)\)。
多项式求 ln
这个感觉也不是很需要,因为你都写了多项式求逆那不就是模板了吗。
多项式开根
考察 \(G(x) = F(x)^{\frac{1}{2}}\),这里可以使用 exp 模板解决多项式开根:
然后使用多项式求 ln 和多项式求 exp。

浙公网安备 33010602011771号