瞎写多项式

· · 算法·理论

多项式

多项式乘法

C(X)=A(X) \times B(X)

一开始我们可以想到使用拉格朗日插值进行求解。

即带入 x_{0} \cdots x_{n} 求点值,得到 Cx_{0} \cdots x_{n} 的点值。

然后使用拉格朗日插值进行求解。

这样仍然是 \mathcal{O}(n^{2})

但是我们发现拉格朗日插值对 x 并没有要求。

假设答案对 P 取模。

NTT

求点值

我们先令 nA 的长度的,mB 的长度,T 为比 n+m 大的最小的 2 的幂次。

我们尝试带入原根,换句话说。

x_{i}=\omega_{T}^{i}

t=\frac{T}{2}

则我们可以发现 x_{i}+x_{i+t}=P

:::info[Proof]

\omega_{T}^{T}=(\omega_{T}^{t})^{2}=1 \because \omega_{T}^{t} \ne 1,\mid \omega_{T}^{t} \mid = 1 \therefore \omega_{T}^{t} = -1 \therefore x_{i}+x_{i+t}=\omega_{T}^{i}+\omega_{T}^{i+t}=\omega_{T}^{i}(1+\omega_{T}^{t})=\omega_{T}^{i}(1-1)=0

:::

所以我们可以将 x 分成两半,后一半是前一半每一项的相反数。

于是我们可以在计算点值的时候按照奇偶项拆分。

于是。

对于奇数的项,取相反数。

对于偶数的项,直接复制。

我们将 A(x) 拆成两个多项式 A_{0}(x),A_{1}(x) 分别为奇数项和偶数项。

则。

A_{0}(\omega_{T}^{j})=\sum_{i=0}^{t}a_{2i}\omega_{T}^{2ij} A_{1}(\omega_{T}^{j})=\omega_{T}^{j}\sum_{i=0}a_{2i+1}\omega_{T}^{2ij}

观察到 \omega 的上下是可以约分的。

:::info[Proof]

\omega_{T}^{2ij}=g^{(\frac{P-1}{T})2ij}=g^{(\frac{p-1}{t})ij}

:::

于是可以得到。

A_{0}(\omega_{T}^{j})=\sum_{i=0}^{t}a_{2i}\omega_{t}^{ij} A_{1}(\omega_{T}^{j})=\omega_{T}^{j}\sum_{i=0}a_{2i+1}\omega_{t}^{ij}

于是我们考虑分治得到答案复杂度是 T \log{T}

还原多项式

就是在点值的基础上再一次带入点值。

由前面我们可以得到。

v_{i}=\sum_{j=0}^{T-1}a_{j}\omega_{T}^{ij}

我们将 v 看成多项式,带入点值 x_{i}=\omega_{T}^{-i} 即可。

FFT

观察到我们 NTT 需要取的 P \in \mathbb{P} 的要求是 P-1=y2^{x} 其中 x \ge \log{n+m} 而我们使用复数进行求解就没有这一种担忧了,因为可以使用 long double 等高精度的数据类型存储。

多项式乘法逆

给定 A(X)B(X) 满足 A(XBG(X) \equiv 1\pmod{x^{n}}

考虑倍增。

已知 A*B'\equiv 1\pmod{x^{\frac{n}{2}}}

B-B'\equiv 1\pmod{x^{\frac{n}{2}}}

平方再乘以 A(X) 可以得到。

B \equiv 2B'-AB'^{2} \pmod{x^{n}}

任意模数多项式乘法逆

采用 3 mod NTT 就是使用 3 个 NTT 友好模数,然后使用 crt 合并。

任意模数多项式乘法

同样可以使用 3 mod NTT 解决。

多项式除法

P4512

特别厉害。

定义一个 reverse 操作 A_{R}(x)=x^{n}A(\frac{1}{x})

F(x)=Q(x)*G(x)+R(x) F(\frac{1}{x})=Q(\frac{1}{x})*G(\frac{1}{x})+R(\frac{1}{x}) F_{R}(x)=Q_{R}(x)*G_{R}(x)+x^{n-m+1}*R_{R}(x)

于是。

F_{R}(x)\equiv Q_{R}(x)*G_{R}(x)\pmod{x^{n-m+1}} Q_{R}(x)\equiv F_{R}(x)*G_{R}^{-1}(x)\pmod{x^{n-m+1}}

多项式开根

照样倍增。

容易得到。

G(X)=\frac{F(X)+H^{2}(X)}{2H(X)}

其中 H(X) 是前一次的答案。

其实到这里可以发现,我们多项式是一个操作依赖前一个操作的,所以常数越堆越大。

例题

P4002

观察到 m=1 的时候 \sum d 是固定的,于是我们发现可以直接一个点一个点的 dp 即可。

观察到 m=2 的时候将 \sum d 是可以拆开乘到 \prod 里面,那么相当于在 \text{Prufer} 序列里面的一种数字里面打上两个标记的方案数,可以不选。

于是我们可以 f_{i,j} 表示到了第 i 个位置打了 j 个标记。

同理可以扩展到 m 个,然后使用多项式乘法优化到 nm\log^{2}{n} 了。

P5395

观察斯特林数时的组合意义,题目中已经给出了,我们观察到需要每一个盒子必然要有球,于是我们考虑容斥。

\begin{Bmatrix} n \\m \end{Bmatrix}=\sum_{i=0}^{m}\frac{i^{n}(-1)^{m-i}}{i!(m-i)!}

于是直接多项式就可以过了。

P5396

可以用生成式函数来做。

假设 f_{n}(x)=\sum_{i \ge 0}\begin{Bmatrix} n \\m \end{Bmatrix}x^{i}

于是。

f_{m}(x)=xf_{m-1}(x)+mxf_{m}(x) f_{m}(x)=\frac{x^{m}}{\prod_{i=1}^{m}(1-ix)}

于是我们使用分治求出下面,然后求逆后偏移 m 位即可。

P5408

容易观察到可以使用生成式函数,然后同上推理,我们可以得到。

就是 \prod_{i=0}^{n-1}(x+i) 然后我们使用分治求出。