多项式总结
总结自 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}\)
多项式开根加求逆即可。
符号化方法
这一部分内容是为了规范我们的思考过程,将灵机一动转化为公式化方法。
无标号组合类和 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 构造
Pointing 构造的意思是在一个组合对象大小种结构一样,标号不同的元素中选择一个关键元素比如说给树定根,对应的 EGF 为(不怎么常用应该):
题目
Extra:拉格朗日反演
有关于复合逆的一个反演形式。具体来说,有:
需要注意的是该反演的使用前提是 \(F, G\) 常数项应为 \(0\),且 \(1\) 次项系数应非 \(0\)。
顺便记录一下扩展拉格朗日反演,其描述内容是:
其中 \(F, G\) 的条件和上述一样,\(H\) 无特殊条件。

浙公网安备 33010602011771号