多项式全家桶
有了
FFT
和NTT
,就有了全世(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\) ?考虑两边平方:
式子两边乘上 \(F(x)\) ,得
所以有:
注意这里的 \(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}}\)
即:
也就是说,我们在模 \(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}\),这就是更优的近似解
根据导数的几何意义(一个点的导数是这个点切线的斜率),有:
所以 \(x_{i+1}\) 可以表示为 \(x_i-\frac{f(x_i)}{f'(x_i)}\)
为什么要单调?因为如果不在单调区间内,初值 \(x_0\) 取值不当的话,可能回导致要多次迭代才能取到零点的近似值(可以参考牛顿分形)
多项式求导
多项式不定积分
(求导的逆运算,\(C\) 可为任意实数)
多项式复合
下面开始正题:
给出多项式 \(f(x)\),求 \(g(x)\) 满足 \(f(g(x))\equiv 0\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)\) 处进行泰勒展开:
显然,由于 \(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}\)
所以上述式子可以化简为:
移项,得到多项式牛顿迭代公式:
4. 多项式开根
即 \(f(x)^2-h(x)\equiv 0\pmod{x^n}\),已知 \(h(x)\),求 \(f(x)\)
直接代入牛顿迭代:
时间复杂度也为 \(O(n\log n)\)
当 \(\pmod x\) 时,需要用二次剩余解出 \(f[0]\)
5. 多项式对数函数(ln)
存在前提条件:\(f[0]=1\)(因为多项式ln
的定义)
这个比多项式指数函数(exp)
简单多了
先给出两个基本式子:
(第二个式子就是复合函数求导,要满足链式法则)
再观察一下 \(ln(f(x))=g(x)\)
考虑将两边求导:
对 \(g'(x)\) 进行积分(求原函数),所以有:
也就是说,我们对 \(f'(x)\) 进行一次求导,一次求逆,乘起来后,最后进行一次积分就搞定了!
6. 多项式指数函数(exp)
存在前提条件:\(f[0]=0\),否则 \(\exp f(x)\) 的常数项将不收敛
Method-1
模仿 多项式ln
的方法,对 \(\exp f(x)\) 进行求导
那么两边的系数就有如下关系:
由多项式求导 \(x^n\rightarrow nx^{n-1}\),得:
又因为 \(f[0]=0\),最后就化成
这可以用 分治FFT
来做,时间复杂度 \(O(n\log^2 n)\)
Method-2
问题等价于:已知 \(h(x)\),求 \(f(x)\) 满足 \(\ln f(x)-h(x)\equiv 0\pmod{x^n}\)
考虑用牛顿迭代
与 多项式开根
类似,复杂度为 \(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\)
那么我们就可以将要求的式子化成:
\(g(x)^k\) 的部分正常做多项式快速幂即可
注意:根据欧拉定理,\(c^k\) 的 \(k\) 不是对 \(mod\) 取模,而是对 \(\phi(mod)=mod-1\) 取模
(注意:如果 \(p\times k>n\) 时,这时候要全输出 \(0\),因此在读入 \(k\) 时就要比较!)
8. 总结
到这里,多项式全家桶基本入门了
剩下一些如三角函数、点值插值等内容,等以后有时间了(退役后)再来慢慢学习
总结一下:
1. 多项式求逆
2. 多项式带余除法
3. 多项式牛顿迭代
4. 多项式开根
5. 多项式对数函数(ln)
6. 多项式指数函数(exp)
7. 多项式快速幂
一般情况: