多项式大杂烩

Froggy

2020-02-05 14:15:53

Personal

# 前言 这个坑咕了好久了,一直没敢填。~~真实原因是我数学太菜~~。 趁着新冠病毒爆发必须宅在家里这几天赶紧补一补qwq。 ~~为了防止文章爆炸~~,同时方便大家阅读,我把代码都扔到云剪切板了,文章里只丢个链接。 文章里面除了多项式全家桶,还会补充一些需要用到的知识,比如'二次剩余'。 方便起见,本文里的 $f[i]$ 表示 $[x^i]f(x)$,即 $f(x)$ 的 $i$ 次项系数。 --- [逐渐更新的vector版多项式板子](https://www.luogu.com.cn/paste/tvrv3ejj) [FFT](https://www.luogu.com.cn/paste/ncktxnmk) [任意模数版本](https://www.luogu.com.cn/paste/bfyeq22c) --- # 目录 >#### 1. 拉格朗日插值 >1.1 公式 >1.2 应用 >1.3 code >#### 2. 快速傅里叶变换 (FFT) >2.1 概况 >2.2 单位根 >2.3 DFT >2.4 IDFT >2.5 蝴蝶变换优化 >2.6 code >#### 3. 快速数论变换 (NTT) >3.1 原根 >3.2 NTT与原根应用 >3.3 code >#### 4. 多项式求逆 >4.1 推式子 >4.2 code >#### 5. 多项式(带余)除法 >5.1 推式子 >5.2 code >#### 6. 多项式对数函数 (多项式Ln) >6.1 简单微积分 >6.2 推式子 >6.3 code >#### 7.多项式指数函数 (多项式exp) >7.1 泰勒展开(泰勒多项式,泰勒公式) >7.2 牛顿迭代 >7.3 推式子 >7.4 code >#### 8.多项式开根 >8.1 二次剩余 >8.2 推式子 >8.3 code >#### 9.多项式快速幂 >9.1 推式子 >9.2 code >#### 10.多项式多点求值 >10.1 推式子 >10.2 code >#### 11.多项式快速插值 >11.1 洛必达法则 >11.2 推式子 >11.3 code >#### 12.多项式三角函数 >12.1 推式子 >12.2 code >#### 13.多项式反三角函数 >13.1 推式子 >13.2 code >#### 14.MTT (FFT进阶) >14.1 FFT的精度优化 >14.2 code >#### 114514.TIPS --- # 正文 一个 $n$ 次**多项式**是形如这样的一个东西: $$f(x)=\sum\limits_{i=0}^n{a_i x^i}\ \ \ (a_n\neq 0)$$ 其中,$n$ 是多项式的最高次幂,$a_{i}$ 为第 $i$ 项系数。 --- ## 1.拉格朗日插值 [(题目)](https://www.luogu.com.cn/problem/P4781) 问题:给定 $n\ (n\leq 2\times 10^3)$ 个点 $(x_i,y_i)$,求经过这 $n$ 的点的 $n-1$ 次多项式。(或求在 $k$ 这个点的取值) 首先珂以暴力高斯消元,不过这样是 $\mathcal{O}(n^3)$,显然布星。 ### 1.1 公式 背住这个公式就好了,证明..太复杂(珂以去问Karry神仙,至少你要知道什么是范德蒙德矩阵的行列式qwq)。 $$f(k)=\sum\limits_{i=1}^n{y_i \prod\limits_{j\neq i}{\frac{k-x_j}{x_i-x_j}}}$$ 这样在 $\mathcal{O}(n^2)$ 的时间复杂度内就可以解决掉了! 如果 $x_{i}=i$ 的之后有更优秀的解决方法: 设 $t=\prod\limits_{i=1}^n{(k-i)}$ 那么式子就变成了: $$f(k)=\sum\limits_{i=1}^n{\left( {\frac{y_i\cdot t}{(i-1)!\ (n-i)!\ (k-i)}\cdot(-1)^{n-i}}\right)}$$ 通过求前缀积和后缀积,这样 $\mathcal{O}(n)$ 或者 $\mathcal{O}(n\log n)$ 就可以解决。 ### 1.2 应用: 求:$\sum\limits_{i=1}^{n}{i^k}$ $\quad (n\leq 10^{13},k\leq 10^5)$ 暴力 $\mathcal{O}(n\log k)$ 布星,需要更优秀的方法。 Karry巨神说:珂以用伯努利数吖!! ↑这个毒瘤东西我们暂且不说↑ ~~老祖宗告诉我们~~,它是一个关于 $n$ 的 $k+1$ 次的多项式。(原理其实是将式子给差分 $k+1$ 次) 举个大家幼儿园都会的例子: 当 $k=1$ 的时候,$f(n)=\frac{n(n+1)}{2}$,是个2次的; 当 $k=2$ 的时候,$f(n)=\frac{n(n+1)(2n+1)}{6}$,是个3次的。 很神奇吧!带入 $x_i=1\dots k+2$ 求出对应的 $y_{i}$,再套改采讲的的式子就 $\mathcal{O}(k\log k)$ 解决掉啦! ### 1.3 ***code*** [***here*** (是那道模板题的)](https://www.luogu.com.cn/paste/5h0itu0e) --- ## 2.快速傅里叶变换 (FFT) [(题目)](https://www.luogu.com.cn/problem/P3803) 问题:给定两个多项式 $f(x)$ 和 $g(x)$, 求 $f(x)*g(x)$,即两个多项式的卷积。 什么是卷积?就是求一个多项式 $p(x)=f(x)*g(x)$ 满足 $p[k]=\sum\limits_{i+j=k}f[i]\times g[j]$ 说白了就是~~小学一年级学的~~多项式乘法嘛! 显然有个 $\mathcal{O}(n^2)$ 的暴力求法,不过FFT在 $\mathcal{O}(n\log n)$ 的时间复杂度内求出来。 ### 2.1 概况 FFT的主要流程就是**系数表达式->点值表达式->系数表达式**。(第一个过程叫DFT,第二个过程叫IDFT) 点值表达式就是用 $n+1$ 个点 $(x_i,y_i)$ 来表示一个 $n$ 次多项式。 为什么要转点值表达式?因为把两个点值表达式乘一起 $\mathcal{O}(n)$ 就搞定了! 把对应的 $x_i$ 和 $y_i$ 乘起来就变成了要求的多项式的点值表达式! DFT和IDFT肿么搞? ### 2.2 单位根 直接带入 $0,1,2,\dots n$ 显然不可取,这样带入复杂度就是 $\mathcal{O}(n^2)$ 的了。 先来讲一讲**单位根**。首先你要知道什么是**虚数**,还要会它的加减乘除运算,不会的又转百度。 先问个问题:$x^n=1$ 在复数范围内的 $n$ 个解分别是什么? 答案:就是把复平面内的单位圆从 $(1,0)$ 开始 $n$ 等分,圆周上 $n$ 个点的坐标就是那 $n$ 个解。设这 $n$ 个解分别是 $\omega_n^0,\omega_n^1,\cdots ,\omega_n^{n-1}$。 显然,$\omega_n^0=1$,$\omega_n^1$ 可以用三角函数搞一下,就是 $\cos\left( \frac{2\pi}{n}\right)+\sin\left( \frac{2\pi}{n}\right)i$,~~这个也很显然,~~ 其实就是三角函数与单位圆的关系,~~不懂三角函数回小学补一补~~。 他们有一些神奇的性质: 1. $\omega_n^k=\omega_{pn}^{pk}$ $\quad (p\in \mathbf{N^*})$ 2. $\omega_n^k=(\omega_{n}^{1})^k$ 3. $\omega_n^{k}=-\omega_{n}^{k+n/2}$ $\quad$ ( $n$ 为偶数 ) ### 2.3 DFT 下面开始重点!**FFT实际上是一个分治的过程**! 我们把 $f(x)$ 拆成两部分,分奇偶打乱。 即:$f(x)=(f[0]+f[2]x^2+\dots +f[n-2]x^{n-2})+(f[1]x+f[3]x^3+\dots +f[n-1]x^{n-1})$ 假设我们已经通过分治求出了: $fl(x)=f[0]+f[2]x+\dots +f[n-2]x^{n/2-1}$ $fr(x)=f[1]+f[3]x+\dots +f[n-1]x^{n/2-1}$ 那么:$f(x)=fl(x^2)+x\cdot fr(x^2)$ 由于 $\omega$ 好的性质,这样分治就珂以搞啦!! 结论就是:(式子根据那些性质很好推,我就不推了) $f(\omega_n^k)=fl(\omega_{n/2}^k)+\omega_n^k\cdot fr(\omega_{n/2}^k)$ $f(\omega_n^{k+n/2})=fl(\omega_{n/2}^k)-\omega_n^k\cdot fr(\omega_{n/2}^k)$ (这个很好记吧,第一个式子就是直接带入的结果,第二个和第一个只有一个正负号的区别) 这样就得到了一坨点值表达式啦! ### 2.4 IDFT 我们得到了一坨点值表达式:$s[k]=\sum\limits_{i=0}^{n-1}{f[i]\cdot (\omega_n^k)^i}$ 那么最后要求的多项式长这样 $n \times p[k]=\sum\limits_{i=0}^{n-1}{s[i]\cdot (\omega_n^{-k})^i}$ **注:** $\omega_n^k=\omega_n^{k\mod n}$,所以 $\omega_n^{-k}=\omega_n^{n-k}$ 证明的话呢带入就好啦,我就不啰嗦了。 然后和DFT的流程一摸一样了,唯一的区别就是带入了**逆单位根**。 码量就可以大大缩小了,只要传一个参数表示现在做的是DFT还是IDFT来决定带入的单位根就行。 ### 2.5 蝴蝶变换优化 通过前面的内容已经珂以写成递归版的FFT啦! 但是常数极大,连模板题都过不掉,所以要写非递归版的。 BUT,要分奇偶打乱,这该肿么搞?直接把每一项的系数放到它最后应该在的位置上就好了。 怎么放?先看一张图。 ![](https://cdn.luogu.com.cn/upload/image_hosting/jgr0vqdj.png) 最后一层是系数分奇偶打乱后最终的位置。(位置编号从0开始) 仔细研究发现,奇偶打乱后每个数的位置是其原数经过二进制反转后的位置 比如 $6=(110)_2$,打乱后的位置就是 $(011)_2=3$ 这个通过 $\mathcal{O}(n)$ 递推珂以得到。 设 $tr_i$ 为 $i$ 经过奇偶打乱后的位置。 递推式: ```cpp tr[i]=((tr[i>>1]>>1)|((i&1)?n>>1:0)); ``` ~~希望大家自行理解。~~ 提示:把 $i$ 拆成 最低位和剩余部分,两部分分别反转,最低位反转是 `((i&1)?n>>1:0)`,剩余部分反转是 `(tr[i>>1]>>1)`。 然后就珂以去实现非递归版(迭代版)的啦!! 还有一个细节,$n$ 不是 $2^k$ 不好搞,那就先把 $n$ 增加到 $2^k$,多出的位置补0就行了。**(同时别忘了把空间开大!)** ### 2.6 ***code*** [***here***](https://www.luogu.com.cn/paste/x827ci2q) --- ## 3.快速数论变换 (NTT) FFT需要算一堆三角函数太慢,而且系数比较大的时候精度也会成问题导致WA。这时候NTT就出场了。 ### 3.1 原根 #### 定义: >若 $g$ 是奇质数 $p$ 的原根,则 $g^1,g^2,\dots,g^{p-1}$ 在模 $p$ 意义下互不相同。 #### 判断一个数 $x$ 是否是奇质数 $p$ 的原根的方法: 先把 $p-1$ 质因数分解,$p-1=p_1^{q_1}\times p_2^{q_2}\times \dots\times p_k^{q_k}$ 若对于 $\forall{i}\in[1,k]$,满足:$x^{(p-1)/{p_i}}\not\equiv1\pmod{p}$,则 $x$ 是 $p$ 的原根。 #### 常用原根: ~~我太懒了~~,直接去[这里](http://blog.miskcoo.com/2014/07/fft-prime-table)康吧。。 一定要记住 $998244353$ 的最小原根是 $3$ 就行! ### 3.2 NTT与原根应用 知道了原根有神马用? 我们把 $g^{(p-1)/t}$ 当作 $\omega_{n}^1$ ($\ t$ 是形如 $2^k$ 的一个数,奇质数 $p$ 要满足形如 $r\cdot 2^k+1\ $,比如 $998244353=119\times 2^{23}+1\ $) 惊奇地发现:$w$ 满足的优秀性质原根都满足!! 这样就好啦!!把FFT原本的单位根换成原根,再也不会有精度问题了!! 其他部分就和FFT一毛一样了。 **但是要注意**,NTT只能处理 $n\leq 2^k$ 的数据,当模数比较毒瘤,比如 $10^9+7$ ,此时 $k=1$,NTT不再能用。(不过不用怕,此后会介绍任意模数NTT,但更加复杂。) ### 3.3 ***code*** [***here***](https://www.luogu.com.cn/paste/ff1shb9c) --- ## 4.多项式求逆 [(题目)](https://www.luogu.com.cn/problem/P4238) 问题:给定 $f(x)$,求 $g(x)$ 满足:$f(x)*g(x)\equiv1\pmod{x^n}$ 求逆的主要思想是**倍增**。(以后好多题目都要用到倍增思想) ### 4.1 推式子: 假设已经求出了一个 $h(x)$,满足 $h(x)\equiv f(x)^{-1}\pmod{x^{\frac{n}{2}}}$ 由于 $g(x)\equiv f(x)^{-1}\pmod{x^n}$ 通过做差得到:$g(x)-h(x)\equiv0\pmod{x^{\frac{n}{2}}}$ 然后在式子两边同时平方(为了把模数的次数凑成 $x^n$ ): $g(x)^2-2*g(x)*h(x)+h(x)^2\equiv0\pmod{x^n}$ 然后机智得把两边同时乘上个 $f(x)$,由于 $f(x)*g(x)\equiv1\pmod{x^n}$ 所以珂以得到: $g(x)-2*h(x)+f(x)*h(x)^2\equiv0\pmod{x^n}$ 即: $$g(x)\equiv 2*h(x)-f(x)*h(x)^2\pmod{x^n}$$ 套个NTT板子就把 $g(x)$ 求出来啦!! 通过这个倍增就好了。 #### 时间复杂度: $\begin{aligned} T(n)&=T(\frac{n}{2})+\mathcal{O}(n\log n) \\ &=\mathcal{O}(n\log n) \end{aligned}$ **不要误以为是两个 $\log$ 了!** (不明白?想一想线段树建树的复杂度) ### 4.2 ***code*** [***here***](https://www.luogu.com.cn/paste/ack6hu17) --- ## 5.多项式(带余)除法 [(题目)](https://www.luogu.com.cn/problem/P4512) 问题:给定 $f(x),g(x)$,求 $q(x),r(x)$ 满足:$f(x)=q(x)*g(x)+r(x)$ 且 $deg_q=deg_f-deg_g,deg_r<deg_g$ **注:** $deg_f$ 为多项式 $f(x)$ 的次数 ### 5.1 推式子: ~~做法玄学~~ 先带入 $\frac{1}{x}$ 得:$f(\frac{1}{x})=q(\frac{1}{x})*g(\frac{1}{x})+r(\frac{1}{x})$ 两边同乘 $x^n$ 得:$x^nf(\frac{1}{x})=x^{n-m}q(\frac{1}{x})*x^mg(\frac{1}{x})+x^nr(\frac{1}{x})$ 定义 $f^R(x)=x^{deg_f}f(\frac{1}{x})$ (等同于把 $f(x)$ 的系数反转后再带入 $x$ ) 则:$f^R(x)=q^R(x)*g^R(x)+r^R(x)\cdot x^{n-m+1}$ 同时模 $x^{n-m+1}$ 珂消去 $r^R(x)\cdot x^{n-m+1}$,得: $f^R(x)\equiv q^R(x)*g^R(x)\pmod{x^{n-m+1}}$ 把 $g^R(x)$ 移一下得: $$q^R(x)\equiv \frac{f^R(x)}{g^{R}(x)}\pmod{x^{n-m+1}}$$ 右边这坨把 $g^R(x)$ 求个逆然后再乘上 $f^R(x)$ 就行了! 由于 $deg_{q^R}<n-m+1$ ,所以 $q^R(x)\mod x^{n-m+1}=q^R(x)$ 这样 $q^R(x)$ 就珂以被求出来啦!只用把 $q^R(x)$ 的系数反转一下就是 $q(x)$,直接用STL库里的reverse函数就行了。 $r(x)$也随便就求出来了: $$r(x)=f(x)-q(x)*g(x)$$ 很神奇吧! 时间复杂度和求逆是一样的:$\mathcal{O}(n\log n)$ ### 5.2 ***code*** [***here***](https://www.luogu.com.cn/paste/8ythbonk) 代码写起来非常恶心。。要调对着标程调半年qwq。 --- ## 6.多项式对数函数 (多项式Ln) [(题目)](https://www.luogu.com.cn/problem/P4725) 问题:给定 $f(x)$,求 $g(x)$ 满足:$g(x)\equiv \ln f(x)\pmod{x^n}$。 想一想 $\ln$ 最初是怎么定义的? 对 $\ln x$ 求导的结果是 $\frac{1}{x}$。也就是 $\frac{\mathrm{d}\ln x}{\mathrm{d}x}=\frac{1}{x}$。 不知道微积分?? ### 6.1 简单微积分 #### 微分 对于一个函数 $f(x)$,如果它在 $x_0$ 处可导,则 $f(x)$ 在 $x_0$ 处的导数为: $$f'(x_0)=\lim\limits_{\Delta x\to 0}{\frac{f(x_0+\Delta x)-f(x_0)}{\Delta x}}$$ 如果你不知道 $\lim$ 是什么,你可以把 $\lim\limits_{\Delta x\to 0}$ 理解为:$\Delta x$ 无限接近 $0$ 但永远也不等于 $0$ 如果函数在连续区间上可导,则函数在这个区间上存在导函数,记作 $f'(x)$ 或 $\frac{\mathrm{d}f(x)}{\mathrm{d}x}$。 ~~不知道极限?那真没救了。~~ 如果 $f(x)$ 是多项式函数,即: $$f(x)=\sum\limits_{i=0}^n a_i x^i$$ 则: $$f'(x)=\sum\limits_{i=1}^{n}i a_i x^{i-1}$$ $\mathcal{O}(n)$ 就可以对一个多项式求导。 #### 积分 积分是微分的逆运算。也就是对一个函数先求个微分然后再积分起来还是原来的函数。 求法就是去求一段函数图像的代数面积。(几何意义) $\int f(x)\mathrm{d}x$ 表示对函数 $f(x)$ 求积分。 同样,对多项式函数积分也是有公式滴! $$\int f(x)\mathrm{d}x=\sum\limits_{i=1}^{n+1}{\frac{a_{i-1} x^{i}}{i}}$$ 由于常数项不确定,它还是个**不定积分**。 $\mathcal{O}(n)$ (需要预处理逆元)或 $\mathcal{O}(n\log n)$ 均可。 #### 链式法则 对一个复合函数该怎么求导? 其实很简单,“拆”一下,分别求个导就好了! $$f'(g(x))=\frac{\mathrm{d}f(g(x))}{\mathrm{d}x}=\frac{\mathrm{d}f(g(x))}{\mathrm{d}g(x)}\cdot \frac{\mathrm{d}g(x)}{\mathrm{d}x}$$ 不需要我解释吧,约分一下就好了。。很显然。 ### 6.2 推式子 知道了简单微积分,解决这道题就小菜一碟啦! 原式:$g(x)\equiv \ln f(x)\pmod{x^n}$ 两边同时求导(用链式法则):$g'(x)\equiv (\ln' f(x))\cdot f'(x)\pmod{x^n}$ 根据 $\frac{\mathrm{d}\ln x}{\mathrm{d}x}=\frac{1}{x}$,式子就变成了: $$g'(x)\equiv \frac{f'(x)}{f(x)}\pmod{x^n}$$ $$g(x)\equiv \int\frac{f'(x)}{f(x)}\pmod{x^n}$$ 然后**求个逆,求个导,求个乘法,求个积分**,开始开心地套板子啦^_^ 时间复杂度仍然是:$\mathcal{O}(n\log n)$ ### 6.3 ***code*** [***here***](https://www.luogu.com.cn/paste/a216590n) 这道题的代码还是非常好写的23333... --- ## 7.多项式指数函数 (多项式exp) [(题目)](https://www.luogu.com.cn/problem/P4726) 问题:给定 $f(x)$,求 $g(x)$ 满足:$g(x)\equiv \mathrm{e}^{ f(x)}\pmod{x^n}$。 $\exp$ 是 $\ln$ 的逆操作,所以要用到 $\ln$,需要先把多项式 $\ln$ 理解透彻。 多项式$\exp$ 需要更多~~恶臭的~~前置知识qwq。 ### 7.1 泰勒展开(泰勒多项式,泰勒公式) 先给出泰勒展开的~~恶心的~~式子: $$f(x)=f(x_0)+\sum\limits_{i=1}^{n}{\frac{f^{(i)}(x_0)}{i!}(x-x_0)^i+R_n(x)}$$ 这个式子需要保证 $f(x)$ 在 $x=x_0$ 的邻域内 $n+1$ 阶可导。其中,$f^{(i)}(x)$ 表示 $f(x)$ 的 $n$ 阶导数,$R_n(x)$ 是佩亚诺(Peano)余项,就是 $(x-x_0)^n$ 的高阶无穷小。(知道就好啦,不用太深究) 珂以形象的理解为通过求导将构造一个函数是它与 $f(x)$ 无限地接近。 这个玩意和生成函数有密切联系,之后再说。 麦克劳林公式就是泰勒公式当 $x_0=0$ 的时候的特殊情况。同样需要保证$f(x)$ 在 $x=0$ 的邻域内 $n+1$ 阶可导。 $$f(x)=f(0)+\sum\limits_{i=1}^{n}{\frac{f^{(i)}(0)}{i!}x^i+R_n(x)}$$ ### 7.2 牛顿迭代 问题:已知 $f(x)$,求 $g(x)$,满足:$f(g(x))\equiv0\pmod{x^n}$ 牛顿迭代的主要思想也是**倍增**。同时要用到上面的泰勒展开,先记住喽! 沿用多项式求逆的思路,假设我们已经求出来了 $h(x)$ 满足:$f(h(x))\equiv0\pmod{x^{\frac{n}{2}}}$ 然后把 $f(g(x))$ 在 $h(x)$ 处泰勒展开, ~~(smg)~~,得到如下的一坨式子: $$f(g(x))=f(h(x))+f'(h(x))(g(x)-h(x))+\frac{f''(h(x))}{2!}(g(x)-h(x))^2+\cdots$$ 由于 $g(x)$ 和 $h(x)$ 的前 $\frac{n}{2}$ 项是相同的,所以: $g(x)-h(x)\equiv0\pmod{x^{\frac{n}{2}}}$ 那么在刚才泰勒展开的那一坨式子中,在 $\mod{x^n}$ 的意义下,由于 $(g(x)-h(x))^i$ $\ \ (i\ge2)$ 的存在,从从第三项开始的值都为0。 原本的式子就被简化成了: $$f(g(x))\equiv f(h(x))+f'(h(x))(g(x)-h(x))\pmod{x^n}$$ 由于 $f(g(x))\bmod x^n=0$,通过移项就能把 $g(x)$ 求出来,得到了下面的这个最终式: $$g(x)\equiv h(x)-\frac{f(h(x))}{f'(h(x))}\pmod{x^n}$$ 像求逆一样迭代一下就好啦! ### 7.3 推式子 最初的式子:$g(x)\equiv \mathrm{e}^{ f(x)}\pmod{x^n}$ 就按常规操作把原来的式子两边同时取对数:$\ln g(x)\equiv f(x)\pmod{x^n}$ 令: $P(g(x))=\ln g(x)-f(x)$ 那么 $P(g(x))\equiv0\pmod{x^n}$ 这就可以套刚才讲的牛顿迭代啦! 假设已经求出来了 $h(x)$ 满足:$P(h(x))\equiv0\pmod{x^{\frac{n}{2}}}$ 则 $g(x)\equiv h(x)-\frac{P(h(x))}{P'(h(x))}\pmod{x^n}$ $P(h(x))$ 怎么求导?看似很麻烦,但仔细思考一下发现,$h(x)$ 才是自变量,这样 $f(x)$ 就是常数,可以忽略掉了。所以: $P'(h(x))=\frac{1}{h(x)}$ 分别把 $h(x)$ 带到式子里面就得到了:$g(x)\equiv h(x)-\frac{\ln h(x)-f(x)}{\frac{1}{h(x)}}\pmod{x^n}$ 化简一下: $$g(x)\equiv h(x)\cdot(1-\ln h(x)+f(x))\pmod{x^n}$$ 然后就是套多项式 $\ln$ 的板子了 时间复杂度:$\mathcal{O}(n\log n)$ ### 7.4 ***code*** [***here***](https://www.luogu.com.cn/paste/icu0ok7k) --- ## 8.多项式开根 [(题目)](https://www.luogu.com.cn/problem/P5205) && [(题目-加强版)](https://www.luogu.com.cn/problem/P5277) 问题:给定 $f(x)$,求 $g(x)$ 满足 $g^2(x)\equiv f(x)\pmod{x^n}$ **注:** 加强版没有保证 $f[0]=1$,此时需要二次剩余。 ### 8.1 二次剩余 [(题目)](https://www.luogu.com.cn/problem/P5491) 问题:给定 $x,p$,保证 $p$ 是**奇质数**,解方程:$x^2\equiv n\pmod{p}$ 先说一说什么是二次剩余。 #### 概念: 对于任意的一个自然数 $n$ ,若对于一个质数 $p$,满足关于 $x$ 的方程 $x^2\equiv n\pmod{p}$ 有整数解,则称 $n$ 是模 $p$ 的二次剩余。 #### 判定方法: 先引入一个**勒让德记号**: $$\left(\frac{n}{p}\right)=\begin{cases} 1&(\,p\nmid n\ \text{且}\,n\,\text{是模}\,p\,\text{的二次剩余})\\ -1&(\,p\nmid n\ \text{且}\,n\,\text{是模}\,p\,\text{的二次非剩余})\\ 0&(\,p\mid n) \end{cases}$$ 根据勒让德记号又有个**欧拉判别准则**: $$\left(\frac{n}{p}\right)\equiv n^{(p-1)/2}\pmod{p}$$ 通过费马小定理珂以证明,这里不详细说了qwq。 现在就可以判断是否有解啦! #### 求解: 如果有解肿么办? 下面讲 **Cipolla算法**: 先随机找到一个自然数 $a\in [0,p)$,令 $\omega^2=a^2-n$,使得 $\left(\frac{\omega^2}{p}\right)=-1$ 其实期望随机2次就出来了。 然后其中一个解就是: $(a+\omega)^{(p+1)/2}$ ($\,$另一个解是 $p-(a+\omega)^{(p+1)/2}\,$) 这个玩意等于 $n$ ? 不可思议,下面证明一下: 别急 首先有个结论: $(a+b)^p\equiv a^p+b^p\pmod{p}$ 证明很简单,拿二项式定理展开一下就好了,不啰嗦啦。 令 $x\equiv (a+\omega)^{(p+1)/2}\pmod{p}$ 则: $x^2\equiv(a+\omega)^{p+1}\pmod{p}$ 根据上面的结论得到:$x^2\equiv(a^p+\omega^p)(a+\omega)\pmod{p}$ 由于:$\left(\frac{\omega^2}{p}\right)\equiv\omega^{p-1}\equiv -1\pmod{p}$,还有费马小定理:$a^{p-1}\equiv1\pmod{p}$ 所以:$x^2\equiv(a^p-\omega)(a+\omega)\equiv(a-\omega)(a+\omega)\equiv a^2-w^2\pmod{p}$ 根据前面的定义:$\omega^2=a^2-n$ 就得到了: $x^2\equiv n \pmod{p}$ 证毕!! 现在唯一的问题就是如何求:$(a+\omega)^{(p+1)/2}$ 由于 $\omega^2$ 的值是已知的,我们珂以把 $\omega$ 看成虚部,两个形如 $a+b\omega$ 相乘会得到: $(a_1+b_1\omega)\cdot(a_2+b_2\omega)=(a_1b_1+a_2b_2)\omega^2+(a_1b_2+a_2b_1)\omega$ 重载一波运算符即可,***code*** [***here***](https://www.luogu.com.cn/paste/xch9qov3) ### 8.2 推式子 (需要用到7.2讲的牛顿迭代,一定要先把那个式子记好喽!) $g(x)^2\equiv f(x)\pmod{x^n}$ 沿用多项式exp的思路,我们设:$P(g(x))=g^2(x)-f(x)$ 则:$P(g(x))\equiv0\pmod{x^n}$ 然后套牛顿迭代:假设已经求出来了 $h(x)$ 满足:$P(h(x))\equiv0\pmod{x^{\frac{n}{2}}}$ 则 $g(x)\equiv h(x)-\frac{P(h(x))}{P'(h(x))}\pmod{x^n}$ 和exp一样,在这里把 $f(x)$ 看成是常数,那么套多项式求导的公式得到:$P'(h(x))=2h(x)$ 把 $h(x)$ 带到式子里面得:$g(x)\equiv h(x)-\frac{h(x)^2-f(x)}{2h(x)}\pmod{x^n}$ 化简之后就得到了最终的结果: $$g(x)\equiv \frac{h(x)^2+f(x)}{2h(x)}\pmod{x^n}$$ 套板子好啦。但还有一个边界就是要求 $g[0]$,它满足: $g[0]^2\equiv f[0]\pmod{p}$ 对于非加强版满足 $f[0]=1$,显然 $g[0]=1$。 对于加强版直接套刚才讲的二次剩余即可。 ### 8.3 ***code*** [***here***](https://www.luogu.com.cn/paste/v3dz6zmd) ***&&*** [***here(加强版)***](https://www.luogu.com.cn/paste/fqgi1v7l) 常数巨大!不开O2最慢点要跑1s+0.05s左右qwq。 其实还有个exp+ln的做法很简便,不过代码难写+常数更大,不建议。 **思考题:** 如果是开 $k$ 次根该怎么搞?提示:还是要用牛顿迭代。 --- ## 9.多项式快速幂 [(题目)](https://www.luogu.com.cn/problem/P5245) & [(加强版)](https://www.luogu.com.cn/problem/P5273) 问题:给定 $f(x),k\ (k\leq 10^{10^5})$,求 $g(x)$ 满足:$g(x)\equiv f^k(x)\pmod{x^n}$ 式子很好推,但要看你的码力+卡常神功了23333。。。 ### 9.1 推式子: 原式:$g(x)\equiv f^k(x)\pmod{x^n}$ 两边同时取对数 ( ln 一下):$\ln g(x)\equiv k\ln f(x)\pmod{x^n}$ 两边同时取指数 ( exp 一下):$g(x)\equiv \mathrm{e}^{k\ln f(x)}\pmod{x^n}$ 然后就是套板子,注意虽然 $k$ 很大,但是它是系数,珂以边读边取余。 珂能大家会有个疑问: Q: 根据欧拉定理/费马小定理,$k$ 不应该对 $998244352$ (即 $p-1$ ) 取模么?为什么要对 $998244353$ 取模? A: 这是在模 $998244353$ 的意义下对 $k\ln f(x)$ 做exp,而 $k$ 是在系数部分的,所以显然 $k$ 要对 $998244353$ 取模。 ### 9.2 ***code*** [***here***](https://www.luogu.com.cn/paste/utt8zl2t) 为毛我这道题没卡常就跑的非常快^_^ --- ## 10.多项式多点求值 [(题目)](https://www.luogu.com.cn/problem/P5050) 问题:给定 $f(x)$ 和 $m$ 个整数 $a_i$ ,分别求出 $f(a_i)$ 秦九韶的暴力 $\mathcal{O}(nm)$ 理论上过不了 (~~然鹅循环展开卡卡常然后夜深人静的时候提交竟然可以过,这时候时间复杂度是 $\mathcal{O}(wyh)$~~ ?? 本题要用**分治**的思想。(终于轮到分治上场了,之前都是倍增) ### 10.1 推式子 我们设两个多项式 $g_0(x)=\prod\limits_{i=1}^{\lfloor\frac{m}{2}\rfloor}{(x-a_i)}$ ,$g_1(x)=\prod\limits_{i=\lfloor\frac{m}{2}\rfloor+1}^{m}{(x-a_i)}$ 方便起见,我们假设 $m$ 是偶数。 显然,$g_0(x),g_1(x)$ 都是 $\lfloor\frac{m}{2}\rfloor$ 次的多项式。 并且,$g_0(a_1)=g_0(a_2)=\cdots=g_0(a_{\frac{m}{2}})=g_1(a_{\frac{m}{2}+1})=\cdots=g_1(a_m)=0$ 我们令 $r_0(x)=f(x)\mod g_0(x)$,$r_1(x)=f(x)\mod g_1(x)$。 即 $f(x)=q_0(x)*g_0(x)+r_0(x)=q_1(x)*g_1(x)+r_1(x)$。 当把 $a_{1 \dots \frac{m}{2}}$ 带入左边的式子中,由于 $g_0(a_i)=0$, 所以 $q_0(x)*g_0(x)=0$,则 $f(x)=r_0(x)$ 此时 $r_0(x)$ 是 $\lfloor\frac{m}{2}\rfloor$ 次的,我们珂以把它当作新的 $f(x)$,类似于上面的过程继续分治下去即可。 右边的同理。 最初珂以先分治NTT求出所有的 $g(x)$,这时候用指针存 $g(x)$ 就非常方便了 (当然也可以用vector)。 求所有的 $r(x)$ 直接套多项式除法的板子即可。 #### 时间复杂度: $\begin{aligned} T(n)&=2\cdot T(\frac{n}{2})+\mathcal{O}(n\log n) \\ &=\mathcal{O}(n\log^2 n) \end{aligned}$ 这回真的是两只 $\log$ 了! ### 10.2 ***code*** [***here***](https://www.luogu.com.cn/paste/g89hk6y6) 这回的代码跑得不慢^_^(但开O2反而更慢了是smg?) --- ## 11.多项式快速插值 [(题目)](https://www.luogu.com.cn/problem/P5158) 问题:给定 $n\ (n\leq 10^5)$ 个点 $(x_i,y_i)$,求经过这 $n$ 的点的 $n-1$ 次多项式。 原题?BUT,这回拉格朗日插值的 $\mathcal{O}(n^2)$ 复杂度显然行不通。 这时候,**我们大力分治**!不过先要知道**洛必达法则**。 ### 11.1 洛必达法则 若函数 $f(x)$ 和 $g(x)$ 满足以下条件: - $\lim\limits_{x\to x_0}f(x)=\lim\limits_{x\to x_0}g(x)=0$ - 两个函数在 $x_0$ 的某去心邻域 $U^\circ (x_0)$ 均可导。 - $g'(x)\neq 0$ 则: $$\lim\limits_{x\to x_0}{\frac{f(x)}{g(x)}}=\lim\limits_{x\to x_0}{\frac{f'(x)}{g'(x)}}$$ ### 11.2 推式子: 还记得开头**拉格朗日插值**么,实际上快插就是对拉格朗日插值的优化,忘了回去复习一下! 为了不使式子看起来这么恶心,当 $j$ 没写上下界约定的时候默认 $j$ 的取值范围和它前面的 $i$ 的取值范围相同。( 此时 $\prod$ 下面只保留 $j\neq i\,$ ) 原式: $$f(x)=\sum\limits_{i=1}^n{y_i \prod\limits_{j\neq i}{\frac{x-x_j}{x_i-x_j}}}$$ 先把这一坨拆成两部分: $$f(x)=\sum\limits_{i=1}^n\left({\frac{y_i}{\prod\limits_{j\neq i}{(x_i-x_j)}}\cdot\prod\limits_{j\neq i}{(x-x_j)}}\right)$$ 我们可以把 $\frac{y_i}{\prod\limits_{j\neq i}{(x_i-x_j)}}$ 当作常数; 设 $v_i=\frac{y_i}{\prod\limits_{j\neq i}{(x_i-x_j)}}$ 令 $g(x)=\prod\limits_{j=1}^n{(x-x_j)}$ ,那么 $\prod\limits_{j\neq i}{(x_i-x_j)}=\frac{g(x)}{x-x_j}(x_i)$ $\frac{g(x)}{x-x_j}$ 这个玩意没法带入怎么办? **洛必达!!** 所以 $\frac{g(x)}{x-x_j}=\frac{g'(x)}{(x-x_j)'}=g'(x)$ 那么 $v_i=\frac{y_i}{g'(x_i)}$ 这个分治NTT求出 $g'(x)$,然后直接套多点求值的板子即可求出 $v_i$ 同样可以把开始的那个大式子给分治NTT了。 设 $f_{l,r}$ 为 $x_{l\cdots r}$ 这一段插出来的多项式。 设 $g_{l,r}$ 为 $\prod\limits_{i=l}^{r}(x-x_i)$ (实际上 $g_{l,r}$ 已经在求 $g'(x)$ 的分治NTT的过程中求出) 设 $mid=\frac{l+r}{2}$ 则: $$\begin{aligned}f_{l,r}&=\sum\limits_{i=l}^r\left({v_i\cdot\prod\limits_{j=l,j\neq i}^{r}{(x-x_j)}}\right) \\ &=\sum\limits_{i=l}^{mid}\left({v_i\cdot\prod\limits_{j=l,j\neq i}^{r}{(x-x_j)}}\right)+\sum\limits_{i=mid+1}^{r}\left({v_i\cdot\prod\limits_{j=l,j\neq i}^{r}{(x-x_j)}}\right) \\ &=\left[\prod\limits_{j=mid+1}^{r}{(x-x_j)}\right]\cdot\sum\limits_{i=l}^{mid}\left({v_i\cdot\prod\limits_{j=l,j\neq i}^{mid}{(x-x_j)}}\right)+ \left[\prod\limits_{j=1}^{mid}{(x-x_j)}\right]\cdot\sum\limits_{i=mid+1}^{r}\left({v_i\cdot\prod\limits_{j=mid+1,j\neq i}^{r}{(x-x_j)}}\right) \\ &=g_{mid+1,r}\cdot f_{l,mid}+g_{l,mid}\cdot f_{mid+1,r} \end{aligned} $$ 直接递归求 $f_{1,n}$ 即可。最后 $f(x)=f_{1,n}$ #### 时间复杂度:$\mathcal{O}(n\log^2 n)$ ### 11.3 ***code*** [***here***](https://www.luogu.com.cn/paste/qumfr4ur) 这是一道卡常好题!还需预处理原根次幂才能过。(具体方法见文末) 这回不开O2真过不了了qwq。卡常卡到我心态爆炸。。。 --- ## 12.多项式三角函数 [(题目)](https://www.luogu.com.cn/problem/P5264) 问题:给定 $f(x)$,求 $g(x)$,满足:$g(x)\equiv\sin f(x)\pmod{x^n}$ 或 $g(x)\equiv\cos f(x)\pmod{x^n}$ emm..又是玄学东西..~~别说三角函数不知道~~ 首先要把多项式exp写得很熟练。 ### 12.1 推式子 相信大家都熟知一个**欧拉公式**: $$\mathrm{e}^{i\theta}=\cos\theta+i\sin\theta$$ 神马?不知道?现在知道了就好。 不过大家至少一定都明白:(初学三角函数就学的内容吧) $\cos\theta=\cos(-\theta),\sin\theta=-\sin(-\theta)$ 那么把 $-\theta$ 带入到欧拉公式得到: $$\mathrm{e}^{i(-\theta)}=\cos\theta-i\sin\theta$$ 这个式子和最初的欧拉公式相加得: $$\cos\theta=\frac{\mathrm{e}^{i\theta}+\mathrm{e}^{-i\theta}}{2}$$ 两式相减得: $$\sin\theta=\frac{\mathrm{e}^{i\theta}-\mathrm{e}^{-i\theta}}{2i}$$ 把 $\theta$ 换成 $f(x)$ 即可变成要求的式子: $$g(x)\equiv\cos f(x)\equiv\frac{\mathrm{e}^{i\cdot f(x)}+\mathrm{e}^{-i\cdot f(x)}}{2}\pmod{x^n}$$ $$g(x)\equiv\sin f(x)\equiv\frac{\mathrm{e}^{i\cdot f(x)}-\mathrm{e}^{-i\cdot f(x)}}{2i}\pmod{x^n}$$ 那个虚数 $i$ 是smg? 别急,先从 $i$ 的定义入手:$i^2=-1$ 所以 $i^2\equiv-1\equiv998244352\pmod{998244353}$ 想到了什么?对!**二次剩余** ! 恰好是有解的,其中较小解为:$i=86583718$ 然后把所有 $i$ 换成 $86583718$,再套个exp的板子就好啦! ### 12.2 ***code*** [***here***](https://www.luogu.com.cn/paste/oqpfjsho) 无任何卡常依然飞快(雾 --- ## 13.多项式反三角函数 [(题目)](https://www.luogu.com.cn/problem/P5265) 问题:给定 $f(x)$,求 $g(x)$ 满足:$g(x)\equiv\arcsin f(x)\pmod{x^n}$ 或 $g(x)\equiv\arctan f(x)\pmod{x^n}$ 上一个板子用欧拉定理,但本题就用不了了qwq。不过珂以求导锕!求导大法吼! ### 13.1 推式子 相信大家在数学课上都学过:(雾 $$\frac{\mathrm{d}\arcsin x}{\mathrm{d}x}=\frac{1}{\sqrt{1-x^2}}$$ $$\frac{\mathrm{d}\arctan x}{\mathrm{d}x}=\frac{1}{1+x^2}$$ 先看**反正弦函数**: 把 $f(x)$ 带入进去得: $\frac{\mathrm{d}\arcsin f(x)}{\mathrm{d}f(x)}=\frac{1}{\sqrt{1-f^2(x)}}$ 再根据**链式法则** (忘了回6.1复习一下): $$\frac{\mathrm{d}\arcsin f(x)}{\mathrm{d}x}=\frac{\mathrm{d}\arcsin f(x)}{\mathrm{d}f(x)} \cdot \frac{\mathrm{d}f(x)}{\mathrm{d}x}=\frac{f'(x)}{\sqrt{1-f^2(x)}}$$ 然后把原式 $g(x)\equiv\arcsin f(x)\pmod{x^n}$ 两边同时求导: $$g'(x)\equiv\frac{\mathrm{d}\arcsin f(x)}{\mathrm{d}x}\equiv\frac{f'(x)}{\sqrt{1-f^2(x)}}\pmod{x^n}$$ 再把两边积分回去就得到要求的: $$g(x)\equiv\arcsin f(x)\equiv\int{\frac{f'(x)}{\sqrt{1-f^2(x)}}\mathrm{d}x}\pmod{x^n}$$ 然后疯狂套板子:微分,开根,求逆,积分! 处理**反正切函数**同理,当成思考题,大家照着上边的过程推一推。 这里就放个结论: $$g(x)\equiv\arctan f(x)\equiv\int{\frac{f'(x)}{1+f^2(x)}\mathrm{d}x}\pmod{x^n}$$ ### 13.2 ***code*** [***here***](https://www.luogu.com.cn/paste/slvo1tp4) 没开O2没卡常就飞快到卡进最优解第二页^_^ --- ## 14.MTT (FFT进阶) [(题目1)](https://www.luogu.com.cn/problem/P4245) && [(题目2)](https://www.luogu.com.cn/problem/P4239) 是我们的老熟人--多项式乘法和多项式求逆 BUT,模数不再是NTT模数,这下子普通的NTT不再能用qwq。 但是珂以选三个NTT模数,然后拿CRT(中国剩余定理)合并。 不过那样要9次NTT,常数太大而且代码不好写qwq。(wtcl,勿喷) ### 14.1 FFT的精度优化 由于 $a_i\leq 10^9$ ,所以常规的FFT的精度会爆炸! 考虑如何优化精度。 可以把系数拆开吖! 把每个系数拆成 $aw+b$ 的形式。 通常 $w$ 取 $2^{15}=32768$ 类似的,我们就把一个多项式 $f(x)$ 拆成了两个。 设 $f_0(x)$ 是 $f(x)$ 的‘低位’,$f_1(x)$ 是 $f(x)$ 的‘高位’。 那么,对于每个多项式: $f(x)=f_0(x)+f_1(x)\cdot w$ 此时把两个多项式相乘就得到了: $$\begin{aligned}f(x)*g(x) &=(f_0(x)+f_1(x)\cdot w)(g_0(x)+g_1(x)\cdot w) \\ &=f_1(x)g_1(x)\cdot w^2+(f_0(x)g_1(x)+f_1(x)g_0(x))w+f_0(x)g_0(x) \end{aligned}$$ 这样分别对 $f_0(x),f_1(x),g_0(x),g_1(x)$ 做DFT, 然后再对 $f_1(x)g_1(x),(f_0(x)g_1(x)+f_1(x)g_0(x)),f_0(x)g_0(x)$ 做IDFT即可 最后合并起来就得到了要求的卷积! 共计7次FFT。 其实还有4次FFT的优秀做法,不过我太菜了qwq。 ### 14.2 ***code*** [***code1***](https://www.luogu.com.cn/paste/p7e1q9gn) ***&&*** [***code2***](https://www.luogu.com.cn/paste/vmlfbung) 这两道道题还卡精度,要开long double (这样似乎比NTT跑得更慢啦?qwq),不过MTT的代码极为好写是真的! --- ## 114514.TIPS qwq,众所周知,多项式的常数极大,并且不是很好写,下面介绍一下我知道tips。 - `i++` 换成 `++i` - 熟练运用`static`,并且可以有效防止变量名重复导致一些奇奇怪怪的错误,并且对卡常有很大帮助 (c++语法知识就不说了⑧...) - 数组大小至少开4倍 - 每次数组最好4倍清空←血的教训(但别清空的时候爆空间喽) - 对于模数,原根,$\pi$ 之类的数最好加const,不要用#define(有时候会有奇效) - 预处理单位根的幂次,,同时修改一下NTT的板子,可以快不少哦![***code here***](https://www.luogu.com.cn/paste/5uoz7wzr) - 加一些 `inline` 和 `register` (大家应该都会) --- # 结语 终于完啦^_^ 希望大家多向我指出细节错误和不足(比如哪里写得不是很详细),我会很感激的! 谢谢大家! (到这里源码有1000+行了qwq)