多项式与点值式
多项式与点值式
正常$\text{DFT/IDFT}$是构造一个特殊的点值式,即$x_i=\omega_{n}^i$
如果能通过题目条件构造出来这样的点值,就可以直接$\text{DFT/IDFT}$
那如果不能的话。。。。。
多项式多点求值
一个多项式$F(x)$我们求它在$x_0,x_0,\cdots x_{m-1}$上的点值
核心是分治+多项式取模,因此常数很大
对于当前分治区间$[l,r]\in[0,m-1]$
需要快速构造一个长度为$\frac{r-l+1} {2}$的等价多项式进入分治区间
令$G_{l,r}(x)=\prod_l^r(1-x_i)$
由于$G_{l,r(x_l)}=\cdots=G_{l,r}(x_r)=0$
所以可以将$F(x)$对于$G_{l,mid}(x)$和$G_{mid+1,r}(x)$分别取模之后得到两个等价式
递归到$[l=r]$时,$F(x)$只剩下常数项
需要被访问的$G(x)$可以预先跑一遍分治NTT求出
那么复杂度就是$O(n\log ^2n)$
这种做法代码实现困难,而且常数非常大
多项式快速插值
对于点对$(x_i,y_i)$
多项式拉格朗日插值的式子是
$$\begin{aligned}F(x) = \sum_{i=0}^{n-1} y_i \prod_{i\ne j} \frac{x-x_j} {x_i-x_j}\end{aligned}$$那么需要快速求出$\prod \frac{1} {x_i-x_j}$
构造多项式$G(x)=\prod (x-x_i)$
那么$\prod (x_i-x_j)=\frac{G} {x-x_i}(x_i)$
由于$G(x),x-x_i$在$x_i$上的点值均为$0$
我们要求的多项式就是$\begin{aligned} \prod_{i\ne j} (x_i-x_j) \end{aligned}=\frac{G(x)} {x-x_i}$
即求出$\frac{G} {x-x_i}(x_i)$
分母分子均为$0$,所以带入洛必达法则$\begin{aligned}\frac{G} {x-x_i}(x_i)=\frac{G'} {(x-x_i)'}(x_i)=G'(x_i)\end{aligned}$
那么求出$G’(x)$,然后多项式多点求值即可
剩下那一部分的答案,可以简单地分治合并上来,$[l=r]$时,多项式是一个常数
合并上来时
$[l,mid]$的答案补上$\prod_{mid+1}^r (x-x_i)$
$[mid+1,r]$的答案补上$\prod_{l}^{mid} (x-x_i)$
即复杂度为$O(n\log ^2n)$
垃圾模板题卡常
应用转置原理对于多点求值的优化
由于这个东西实在是太新了,所以没有什么文献可以看
关于转置原理的前置定义
矩阵的转置:
对于$n\cdot m$的矩阵$M$,它的转置$M^{T}$为交换行列坐标后得到的$m\cdot n$的矩阵
其满足运算性质:
1.逆: ${(A^T)}^T=A$
2.和:$(A+B)^T=A^T+B^T$
3.反积:$(AB)^T=B^TA^T$
初等矩阵:
初等矩阵是指单位矩阵通过初等变换(交换行列,某一行(列)乘上$k$加到另一行(列)上,类似高斯消元)得到的矩阵
对于计算$b=A\cdot a$,其中$A$为矩阵,$a,b$为列向量
考虑先计算$b’=A^T\cdot a$
出计算$b’$的过程,这可以分解成若干步操作(或说是初等矩阵)$E_1,E_2,\cdots E_k$
即$b’=E_1\cdot E_2\cdot E_3\cdots E_k\cdot a$
将$E_i$倒序执行,并且每一步都换成原先操作的转置$E_i^T$,就能得到$A\cdot a$
即$b=E^T_k\cdot E^T_{k-1}\cdots E^T_1\cdot a$
应用转置原理的优化核心
如果把多项式系数视为列向量$F$,则可以把多项式多点求值的过程视为一个矩阵运算$M$
为了便于描述,设要求的点值和多项式项数均为$n$
设要求的点横坐标为$x_i$,则$M$是范德蒙德矩阵
$1$ | $x_0^1$ | $x_0^2$ | … |
---|---|---|---|
1 | $x_1^1$ | $x_1^2$ | … |
1 | $x_2^1$ | $x_2^2$ | … |
… |
分析会发现我们要求的实际上是$b=M\cdot F$(到底是谁对矩阵乘法有误解?)
现在来将问题转置,先假装求$b’=M^T\cdot F$
$1$ | 1 | 1 | … |
---|---|---|---|
$x_0^1$ | $x_1^1$ | $x_2^1$ | … |
$x_0^2$ | $x_1^2$ | $x_2^2$ | … |
… |
实际$M^T\cdot F$得到的结果用形式幂级数表示是
$\displaystyle\sum F_i\sum_{j=0}^{n-1}x_i^j\equiv \sum \frac{F_i} {1-x_ix}\pmod {x^n}$
求$\displaystyle M^T\cdot F= \sum \frac{F_i} {1-x_ix}\pmod {x^n}$
可以用两次分治 $\text{NTT}$ 解决,大致过程可以描述为
1.将问题转化为求$\begin{aligned} \frac{\sum F_i\prod _{i\ne j} {(1-x_jx)} } {\prod (1-x_ix)}\end{aligned} $
2.对于分治节点$[L,R]$,求得$T(L,R)=\prod_{i=L}^R{(1-x_i)}$
3.从下往上合并,每次合并答案为$A(L,R)=A(L,mid)\cdot T(mid+1,R)+A(mid+1,R)\cdot T(L,mid)$
4.最后将答案$A(0,n-1)$除以$\prod(1-x_ix)$
然后我们考虑把所有的操作都反过来并且换成转置,求得$M\cdot F$
因为过程中涉及到多项式卷积,设其转置运算为$\oplus$
我们知道普通的多项式卷积为$F(x)\cdot G(x)=\sum_i\sum_j [x^i]F(x)[x^j]G(x)x^{i+j}$
则其转置为$mul^T(F(x),G(x))=F(x)\oplus G(x)=\sum_i\sum_{j\leq i} [x^i]F(x)[x^j]G(x)x^{i-j}$
可以看到这个操作会导致多项式项数降低,若原先$F(x),G(x)$最高项为$n,m$,则转置卷积后最高项为$n-m$
那么给出整个转置后的过程为
1.在$F(x)$后面加上若干个$0$,求出$\displaystyle A(0,n-1)=F(x) \oplus \frac{1} {\prod(1-x_ix)}$的前$n$项
2.对于每个分治节点,依然预处理$\displaystyle T(L,R)=\prod_{i=L}^R{(1-x_ix)}$
3.从顶向下递归,向子节点下传
$A(L,mid)= A(L,R)\oplus T(mid+1,R)$
$A(mid+1,R)= A(L,R)\oplus T(L,mid)$
递归到子节点时,只剩一项,即是每一个点值
关于这个优化的效果:
1.不需要写多项式除法和取模了!
2.第二次分治的过程中调用的$mul^T$长度短一倍
下面这份代码是优化过的版本,能快一倍左右,但关键还是代码短听说可以被卡常卡到1s跑1e6
1 |
|