多项式模板学习笔记
多项式乘法
存在多项式 \(F(z)=\sum_{i=0}^na_iz^i,G(z)=\sum_{i=0}^mb_iz^i\),我们定义多项式乘法:
多项式的点值表达
一个 \(n\) 次函数可以用平面上的 \(n+1\) 个点来表达。
所以我们可以把一个 \(n\) 次多项式从 系数表达 转化成 \(n+1\) 个点来表达,这一步也叫 求值。
然后如果 \(F(z)\) 过 \((x_1,y_1)\),\(G(z)\) 过 \((x_1,y_2)\),那么 \((F*G)(x_1)=y_1y_2\)。
所以我们只需要在 \(F,G\) 上各寻找 \(\deg F+\deg G+1\) 个点即可确定 \(F*G\)。
我们变成了 用系数找出点值表达 和 用点值表达表达出系数。
FFT
FFT 可以在 \(O(n\log n)\) 时间复杂度内解决多项式乘法。
DFT
我们先考虑如何找出 \(n+m+1\) 个点值。
前置知识:单位根
单位根 / \(n\) 次单位根:即 \(n\) 次幂为 \(1\) 的复数,用 \(w_n\) 表示
显然 \(n\) 次单位根共\(n\)个,写作\(w^k_{n}\) 的形式
根据 复数乘法模长相乘,幅角相加的法则,发现单位根只存在于半径为\(1\)的单位圆上
且 \(n\) 次单位根将此单位圆 \(n\) 等分
然后单位根有有如下性质:
- \(w_0^n=1\)
- \(w^{i}_nw^j_n=w^{i+j}_n\)
- \(w^{ak}_{an}=w^{k}_{n}\)
- \(w^{k+\frac n2}_n=-w^{k}_n(n\equiv 0(\bmod 2))\)
我们考虑一个 \(n\) 项多项式 \(F(z)=\sum_{i=0}^{n-1}a_iz^i\),然后我们把 \(n\) 补成 \(2\) 的次幂,所以可以平均分开。
得到:
设 \(FL(z)=\sum_{i=0}^{(n-1)/2}a_{2i}z^i,FR(z)=\sum_{i=0}^{(n-1)/2}a_{2i+1}z^i\)。
显然我们可以发现:
我们代入一个 \(w^k_n,w^{k+\frac n 2}_n(k<\frac n 2)\),得到:
所以如果我们只需要知道 \(FL,FR\) 在 \(w^0_{n/2},w^1_{n/2},w^2_{n/2},\cdots w^{n/2-1}_{n/2},\) 处的点值表达即可,然后可以 \(O(n)\) 的得到 \(F(z)\) 在 \(w^0_{n},\cdots w^{n-1}_n\) 处的点值。
然后我们分治下去即可,时间复杂度 \(T(n)=2T(\frac n 2)+O(n)=O(n\log n)\)。
然后我们考虑点值转为系数表达。
IDFT
我们现在得到了一大堆点值,现在要把他转化成系数。
结论是我们用 \(w^{-1}_n\) 代替 \(w^1_n\) 做上面的部分然后除以 \(n\) 即可。
证明:我们设 \(G=\text{DFT}(F)\),那么我们知道
我们需要证明:
至于邪恶的蝴蝶变换,这个可以自己手玩得到。
破除封建迷信:STL 的 complex 跑的很快,根本不需要手写。
三次变两次
我们设 \(P=F+Gi\),那么我们得到 \(P^2=F^2-G^2+2FGi\),这样我们只用做一次 DFT 和一次 IDFT 即可。
三次变两次不掉精度。
MTT
系数过大的情况下,FFT 会有相当程度的精度误差。
我们把 \(F(x),G(x)\) 分别拆成 \(A(x)+cB(x),C(x)+cD(x)\),然后我们构造函数 \(T(x)=C(x)+D(x)i\)。
然后我们要得到 \(A(x)C(x)+c(A(x)D(x)+B(x)C(x))+c^2B(x)D(x)\)。
然后我们可以用 \(A(x)T(x),B(x)T(x)\) 得到 \(A(x)C(x)+A(x)D(x)i\) 和 \(B(x)C(x)+B(x)D(x)i\)。
然后就能用 \(3\) 次DFT 和 \(2\) 次 IDFT 解决问题。
NTT
就是用 \(g^{(p-1)/n}_n\) 代替 \(w^1_n\)。
多项式牛顿迭代
主要是解决以下问题。
给出函数 \(g(x)\),求出一个 \(f(x)\),使得
\[g(f(x))\equiv 0(\bmod x^n) \]
我们递归考虑,假设我们已经知道 \(t(x)\),使得:
那么我们知道
我们考虑将 \(g(x)\) 在 \(t(x)\) 处泰勒展开,我们得到:
后面那一截等于 \(0\),所以我们知道:
然后递推求解即可。
多项式求逆
给定多项式 \(A(x)\),求解多项式 \(B(x)\),使得 \(A(x)B(x)\equiv 1(\bmod x^n)\)
考虑令 \(G(z)=\frac 1 z-A(x)\),那么 \(G'(z)=-\frac 1 {z^2}\),所以我们得到:
多项式开根
给定多项式 \(A(x)\),求解多项式 \(B(x)\),使得 \(B^2(x)\equiv A(x)(\bmod x^n)\)
我们考虑令 \(G(z)=z^2-A(x)\),则我们知道 \(G'(z)=2z\),所以我们知道 \(F(x)=t(x)-\frac {t^2(x)-A(x)}{2t(x)}=\frac {A(x)+t^2(x)}{2t(x)}\)
然后倍增求解即可,时间复杂度 \(T(n)=T(\frac n2)+O(n\log n)=O(n\log n)\)。
多项式 ln
给定多项式 \(A(x)\),求解多项式 \(B(x)\),使得 \(B(x)\equiv \ln A(x)(\bmod x^n)\)
多项式 exp
给定多项式 \(A(x)\),求解多项式 \(B(x)\),使得 \(B(x)\equiv \exp A(x)(\bmod x^n)\)
考虑牛顿迭代,设 \(G(z)=\ln z- A(x)\),则 \(G'(z)=\frac 1 z\),所以我们得到:
倍增求解即可,时间复杂度为 \(O(n\log n)\)。
多项式快速幂
给定多项式 \(A(x)\),常数 \(k\),求解多项式 \(B(x)\),使得 \(B(x)\equiv A^k(x)(\bmod x^n)\)
\(O(n^2)\) 多项式操作
由于 shaber FFT 是高贵的 10 级考点,所以我们如果不想背那个 shaber 东西就用 \(O(n^2)\) 多项式操作吧。
可能在集合幂级数上可以使用。
多项式乘法
直接做即可。
多项式求逆
多项式 \(\ln\)
多项式 \(\exp\)
两边提取系数即可。
多项式快速幂
提取系数递推即可。
Boston-mori 算法
对于两个 \(k\) 次多项式 \(F(z),G(z)\),我们可以在 \(O(k\log k\log n)\) 的时间复杂度内求出
如果 \(n=1(\bmod 2)\) 的话,\(Ans=[z^{n/2}]\frac {c_{odd}(z)}{v(z)}\)。
否则 \(Ans=[z^{n/2}]\frac {c_{even}(z)}{v(z)}\)。
所以我们只需要 \(O(\log n)\) 次多项式乘法即可。
Chirp Z
减法卷积即可,\(\mathcal O(n\log n)\)
多项式连续点值平移
然后我们知道:
\(\mathcal O(n\log n)\)。
多项式复合逆
已知多项式 \(F(z)\) 且 \([z^0]F(z)=0,[z^1]F(z)\not= 0\),求 \(G(z)\) 使得 \(G(F(z))=z\)。
考虑拓展拉反:
所以我们得到:
如果我们得到了 \((\frac z {G(z)})^n\) ,那么我们可以简单求出 \(G\),现在问题变成
我们考虑有一个经典的东西是:
由于这会让各种次数的浙西混在一起,我们考虑引入第二元 \(y\),变成求解:
然后我们考虑 Bostan-Mori 求解分式远处求值问题。
我们发现每一次 \(x\) 次数减半, \(y\) 次数加倍,所以项数乘积一直是 \(O(n)\) 的,复杂度为 \(O(n\log^2 n)\)。
转置原理
这个很有用的,也许你可以去学习
大概是对于我们需要求 \(M{\bf v}\) ,假设我们有方便的算法 \(\mathcal B\) 求出 \(M^T\bf v\),那么我们将 \(\mathcal B\) 的算法流程转置即可在几乎不改变时间复杂度的情况下求得 \(M\bf v\)。
多项式多点求值
显然我们想要求出
我们考虑转置:
然后这个东西我们发现其生成函数就是:
所以 \(\mathcal B\) 就是分治 NTT 。
然后我们考虑 \(\mathcal B^T\),我们将转移顺序倒序,再改变贡献的方向即可。
比如对于 \(c_{i+j}\gets \sum a_ib_j\),转置后得到:
减法卷积即可。

浙公网安备 33010602011771号