多项式全家桶

有了 FFTNTT,就有了全世(jia)界(tong) ——command_block


1. 多项式求逆

定义:当满足 \(f(x)*g(x)\equiv 1\pmod {x^n}\),则 \(f(x), g(x)\) 互为逆元

我们考虑递归求解:设我们需要求出 \(F(x)\) 的乘法逆元为 \(R(x)\)

若我们已经求出 \(R'(x)\),满足 \(F(x)*R'(x)\equiv 1\pmod {x^{n/2}}\)

显然也有 \(F(x)*R(x)\equiv 1 \pmod {x^{n/2}}\) (因为 \(x^n\)\(x^{n/2}\) 的倍数)

两式相减,有 \(F(x)*(R(x)-R'(x))\equiv 0 \pmod{x^{n/2}}\)

也就是 \(R(x)-R'(x)\equiv 0\pmod{x^{n/2}}\)

那如何将模数上升到 \(x^n\) ?考虑两边平方:

\[\begin{aligned} (R(x)-R'(x))^2&\equiv 0\pmod{x^{n}}\\ R(x)^2-2R(x)R'(x)+R'(x)^2&\equiv 0\pmod{x^{n}}\\ \end{aligned}\]

式子两边乘上 \(F(x)\) ,得

\[R(x)-2R'(x)+F(x)R'(x)^2\equiv 0\pmod{x^{n}} \]

所以有:

\[R(x)=2R'(x)-F(x)R'(x)^2\equiv 0\pmod{x^n} \]

注意这里的 \(n/2\)向上取整

当递归到 \(mod\ x^{len}\) 时, NTT 的长度只需要取 \(len\times 2\) (因为 \(>=len\) 的系数一定为 \(0\),不需要卷),因此时间复杂度为 \(O(n\log n)\)

代码


2. 多项式带余除法

代码(封装得应该还不错)

先放代码后解析的zuytong是屑

先考虑没有余项的除法:\(Q(x)=\frac{F(x)}{G(x)}\)

显然就是求出 \(G(x)\) 的乘法逆元,再卷上 \(F(x)\)

现在回到有余项的除法:\(Q(x)*G(x)=F(x)-R(x)\)

\(F_R(x)\) 表示 将 \(F(x)\) 的系数反转(即\(F[i]\rightarrow F[n-i]\)

显然有 \(f(x)=x^n F_R(\frac{1}{x})\)

因为 \(Q(\frac{1}{x})*G(\frac{1}{x})=F(\frac{1}{x})-R(\frac{1}{x})\)

左右同时乘上 \(x^n\)\(x^{n-m}Q(\frac{1}{x})*x^mG(\frac{1}{x})=x^nF(\frac{1}{x})-x^nR(\frac{1}{x})\)

根据上述公式,有 \(Q(x)*G(x)=F(x)-x^{n-m+1}R(x)\)

对左右取模 \(x^{n-m+1}\),就有 \(Q(x)*G(x)\equiv F(x)\pmod{x^{n-m+1}}\)

即:

\[Q(x)\equiv \frac{F(x)}{G(x)}\pmod{x^{n-m+1}} \]

也就是说,我们在模 \(x^{n-m+1}\) 意义下做无余项除法即可

又因为 \(Q(x)\) 的次数为 \(n-m<n-m+1\),所以可以直接求出 \(Q(x)\)

至于余项,有 \(R(x)=F(x)-Q(x)*G(x)\)

一定要分清次数!多一少一影响都是巨大的!


3. 多项式牛顿迭代

牛顿迭代

牛顿迭代就是求:函数 \(F(x)\) 在一段连续且单调的值域 \([a,b]\) 上的零点近似解

方法:设当前的近似解为 \(x_i\),我们作出 \((x_i,f(x_i))\) 的切线,与 \(x\) 轴的交点为 \(x_{i+1}\),这就是更优的近似解

根据导数的几何意义(一个点的导数是这个点切线的斜率),有:

\[f'(x_i)=\frac{f(x_i)}{x_i-x_{i+1}} \]

所以 \(x_{i+1}\) 可以表示为 \(x_i-\frac{f(x_i)}{f'(x_i)}\)

为什么要单调?因为如果不在单调区间内,初值 \(x_0\) 取值不当的话,可能回导致要多次迭代才能取到零点的近似值(可以参考牛顿分形

多项式求导

\[f'(x)=\sum_{i=1}^n i\times f[i]x^{i-1} \]

多项式不定积分

\[f'(x)=C+\sum_{i=0}^n \frac{f[i]}{i}x^{i+1} \]

(求导的逆运算,\(C\) 可为任意实数)

多项式复合

\[f(g(x))=\sum_{i=0}^nf[i]g(x)^i \]

下面开始正题:

给出多项式 \(f(x)\),求 \(g(x)\) 满足 \(f(g(x))\equiv 0\pmod{x^n}\)

先抛结论

\[g(x)=g_{last}(x)-\frac{f(g_{last}(x))}{f'(g_{last}(x))}\pmod{x^n} \]

和求逆类似的思路,我们考虑倍增:

\(n = 1\) 时,\(f(g(x))\equiv 0 \pmod{x}\) 需要单独求出

设我们当前已经知道了 \(f(g(x))\equiv 0\pmod{x^{n/2}}\) 的解 \(g_0(x)\)

我们考虑对 \(f(x)\)\(g(x)\) 处进行泰勒展开:

\[f(g(x))=\sum_{i=0}^\infty \frac{f^{(i)}(g_0(x))}{i!}(g(x)-g_0(x))^i\equiv 0 \pmod{x^n} \]

显然,由于 \(g(x)\)\(g_0(x)\) 的前 \(n/2\) 个系数是相同的,说明 \(g(x)-g_0(x)\) 只有 \(n/2\) ~ \(n-1\) 上系数不为 \(0\)

所以当 \(i=2\) 时,\((g(x)-g_0(x))^i\) 的最低次数项为 \(x^n\),因此有:当 \(i \ge 2\) 时,\((g(x)-g_0(x))^i\equiv 0\pmod{x^n}\)

所以上述式子可以化简为:

\[\sum_{i=0}^\infty \frac{f^{(i)}(g_0(x))}{i!}(g(x)-g_0(x))^i\equiv f(g_0(x))+f'(g_0(x))(g(x)-g_0(x))\equiv 0\pmod{x^n} \]

移项,得到多项式牛顿迭代公式:

\[g(x)=g_0(x)-\frac{f(g_0(x))}{f'(g_0(x))} \]


4. 多项式开根

\(f(x)^2-h(x)\equiv 0\pmod{x^n}\),已知 \(h(x)\),求 \(f(x)\)

直接代入牛顿迭代:

\[f(x)\equiv f_0(x)-\frac{f_0(x)^2-h(x)}{2f_0(x)}\equiv\frac{f_0(x)^2+h(x)}{2f_0(x)}\pmod{x^n} \]

时间复杂度也为 \(O(n\log n)\)

\(\pmod x\) 时,需要用二次剩余解出 \(f[0]\)

代码

二次剩余版本


5. 多项式对数函数(ln)

存在前提条件:\(f[0]=1\)(因为多项式ln定义

这个比多项式指数函数(exp)简单多了

先给出两个基本式子:

\[ln'(x)=\frac{1}{x},\ f(g(x))'=f'(g(x))g'(x) \]

(第二个式子就是复合函数求导,要满足链式法则)

再观察一下 \(ln(f(x))=g(x)\)

考虑将两边求导:

\[ln'(f(x))f'(x)=g'(x) \]

\[\frac{f'(x)}{f(x)}=g'(x) \]

\(g'(x)\) 进行积分(求原函数),所以有:

\[g(x)=\int(\frac{f'(x)}{f(x)}) \]

也就是说,我们对 \(f'(x)\) 进行一次求导,一次求逆,乘起来后,最后进行一次积分就搞定了!

代码


6. 多项式指数函数(exp)

存在前提条件:\(f[0]=0\),否则 \(\exp f(x)\) 的常数项将不收敛

Method-1

模仿 多项式ln 的方法,对 \(\exp f(x)\) 进行求导

\[\exp' f(x)=\exp f(x)\ f'(x) \]

那么两边的系数就有如下关系:

\[[x^{n-1}]\exp' f(x)=\sum_{i=0}^{n-1}[x^i]\exp f(x)\ [x^{n-1-i}]f'(x) \]

由多项式求导 \(x^n\rightarrow nx^{n-1}\),得:

\[n[x^{n}]\exp f(x)=\sum_{i=0}^{n}[x^i]\exp f(x)*(n-i)[x^{n-i}]f(x) \]

又因为 \(f[0]=0\),最后就化成

\[n[x^{n}]\exp f(x)=\sum_{i=0}^{n-1}[x^i]\exp f(x)*(n-i)[x^{n-i}]f(x) \]

这可以用 分治FFT 来做,时间复杂度 \(O(n\log^2 n)\)

Method-2

问题等价于:已知 \(h(x)\),求 \(f(x)\) 满足 \(\ln f(x)-h(x)\equiv 0\pmod{x^n}\)

考虑用牛顿迭代

\[\begin{aligned} f(x)&=f_0(x)-\frac{\ln f_0(x)-h(x)}{\frac{1}{f_0(x)}}\\ &= f_0(x)-f_0(x)(\ln f_0(x)+h(x))\\ &= f_0(x)(1-\ln f_0(x)+h(x)) \end{aligned}\]

多项式开根 类似,复杂度为 \(O(n\log n)\)

代码


7. 多项式快速幂

显然我们可以用 \(O(n\log^2 n)\) 的快速幂+多项式乘法

但还有一种方法:\(f(x)^k=(e^{\ln f(x)})^k=e^{k*\ln f(x)}\)

这应该是 \(O(n\log n)\) 的(但听说这个算法的常数高达 \(\log\) ?)

显然,这有一个限制:\(f[0]=1\)

代码

那如果 \(f[0]\not= 1\) 呢?

那么就想方法让它变成 \(1\)

显然,\(f(x)\) 可以表示为 \(g(x)\times (c\times x^p)\)

这里的 \(p\)\(f(x)\) 中第一个系数不为 \(0\) 的项,\(c\) 是这个项的系数

形式化地,可以表示为:\(c=f[p]\not= 0\)\(\forall\ 0\le i <p,\ f[i]=0\)

那么我们就可以将要求的式子化成:

\[f(x)^k=(\frac{f(x)}{c\times x^p})^k\times c^kx^{pk}=g(x)^k\times c^kx^{pk} \]

\(g(x)^k\) 的部分正常做多项式快速幂即可

注意:根据欧拉定理,\(c^k\)\(k\) 不是对 \(mod\) 取模,而是对 \(\phi(mod)=mod-1\) 取模

代码

(注意:如果 \(p\times k>n\) 时,这时候要全输出 \(0\),因此在读入 \(k\) 时就要比较!)


8. 总结

到这里,多项式全家桶基本入门了

剩下一些如三角函数、点值插值等内容,等以后有时间了(退役后)再来慢慢学习

总结一下:

1. 多项式求逆

\[R(x)=2R'(x)-F(x)R'(x)^2\equiv 0\pmod{x^n} \]

2. 多项式带余除法

\[Q(x)\equiv \frac{F(x)}{G(x)}\pmod{x^{n-m+1}} \]

\[R(x)=F(x)-Q(x)*G(x) \]

3. 多项式牛顿迭代

\[g(x)=g_0(x)-\frac{f(g_0(x))}{f'(g_0(x))} \]

4. 多项式开根

\[f(x)\equiv f_0(x)-\frac{f_0(x)^2-h(x)}{2f_0(x)}\equiv\frac{f_0(x)^2+h(x)}{2f_0(x)}\pmod{x^n} \]

5. 多项式对数函数(ln)

\[g(x)=\int(\frac{f'(x)}{f(x)}) \]

6. 多项式指数函数(exp)

\[f(x)= f_0(x)(1-\ln f_0(x)+h(x)) \]

7. 多项式快速幂

\[f(x)^k=e^{k*\ln f(x)} \]

一般情况:

\[f(x)^k=(\frac{f(x)}{c\times x^p})^k\times c^kx^{pk} \]

posted @ 2022-04-23 21:46  zuytong  阅读(72)  评论(0编辑  收藏  举报