多项式全家桶

下面的所有知识均属多项式范畴。


前言

本文略去多项式的定义,毕竟初中数学都讲过。

本文会出现一些可能没有见过的表达:

  • 对于一个关于 x x x 的多项式 f ( x ) f(x) f(x),有时也称其最高次项次数为 f ( x ) f(x) f(x)度数
  • 多项式同样定义了四则运算,包括常数与多项式的四则运算多项式之间的四则运算,同时也衍生出了同余符号 ≡ \equiv 、对数函数 ln ⁡ ( f ( x ) ) \ln(f(x)) ln(f(x)),指数函数 exp ⁡ ( f ( x ) ) \exp(f(x)) exp(f(x)) 等等。
  • 下文一般采用 f ( x )     m o d   x n f(x)~\bmod x^n f(x) modxn 来表示多项式 f ( x ) f(x) f(x) 的所有次数小于 n n n 的项之和。
  • 下文有时会采用 [ x k ] f ( x ) [x^k]f(x) [xk]f(x) 表示多项式次数为 k k k 的项。

注意:本文的知识环环相扣请勿乱序阅读


拉格朗日插值

插值,通俗地讲,就是指通过多项式在某些点的值求出整个多项式的表达式

拉格朗日插值就是计算插值的一种方法,它支持通过 n + 1 n + 1 n+1 个点插出一个度数为 n n n 的多项式。

按惯例,献上模板题

首先对于多项式 f ( x ) f(x) f(x),必然满足 f ( x ) ≡ f ( a )   (   m o d   ( x − a ) ) f(x) \equiv f(a)~(\bmod (x - a)) f(x)f(a) (mod(xa))

证明:

转化为 f ( x ) − f ( a ) ≡ 0   (   m o d     ( x − a ) ) f(x) - f(a) \equiv 0~(\bmod~(x - a)) f(x)f(a)0 (mod (xa))

设左侧的多项式为 g ( x ) g(x) g(x),显然其常数项为 0 0 0

又因为其第 i i i 项为 p i ( x i − a i ) p_i(x^i - a^i) pi(xiai) p i p_i pi 为系数),并且 x i − a i x^i - a^i xiai 必定可以分解为 ( x − a ) ⋅ q ( x ) (x - a) \cdot q(x) (xa)q(x) 的形式( q ( x ) q(x) q(x) 为另一个多项式),所以得证。

所以我们可以得到一个关于 f ( x ) f(x) f(x) 线性同余方程组:
{ f ( x ) ≡ y 1   (   m o d   ( x − x 1 ) ) f ( x ) ≡ y 2   (   m o d   ( x − x 2 ) ) f ( x ) ≡ y 3   (   m o d   ( x − x 3 ) ) ⋮ f ( x ) ≡ y n   (   m o d   ( x − x n ) ) \left\{ \begin{matrix} f(x) \equiv y_1~(\bmod (x - x_1)) \\ f(x) \equiv y_2~(\bmod (x - x_2)) \\ f(x) \equiv y_3~(\bmod (x - x_3)) \\ \vdots \\ f(x) \equiv y_n~(\bmod (x - x_n)) \end{matrix} \right. f(x)y1 (mod(xx1))f(x)y2 (mod(xx2))f(x)y3 (mod(xx3))f(x)yn (mod(xxn))
这里可以使用中国剩余定理解方程组(这里就没有必要关注它们是否互质了)。

我们可以设 M = ∏ i = 1 n ( x − x i ) M = \prod_{i = 1}^n (x - x_i) M=i=1n(xxi) M i = M ( x − x i ) = ∏ j ≠ i ( x − x j ) M_i = \frac{M}{(x - x_i)} = \prod_{j \ne i} (x - x_j) Mi=(xxi)M=j=i(xxj)

M i M_i Mi 在模 x − x i x - x_i xxi 意义下的逆元为 ∏ j ≠ i 1 x i − x j \prod_{j \ne i}\frac{1}{x_i - x_j} j=ixixj1

(因为 M i M i − 1 = ∏ j ≠ i x − x j x i − x j ≡ 1   (   m o d   ( x − x i ) ) M_i M_i^{-1} = \prod_{j \ne i}\frac{x - x_j}{x_i - x_j} \equiv 1~(\bmod (x - x_i)) MiMi1=j=ixixjxxj1 (mod(xxi)),则对于每一个 j ≠ i j \ne i j=i 都存在 $ x - x_j \equiv x_i - x_j~(\bmod (x - x_i))$,移项可得 x − x i ≡ 0   (   m o d   ( x − x i ) ) x - x_i \equiv 0~(\bmod (x - x_i)) xxi0 (mod(xxi)),这显然是成立的。)

所以有 f ( x ) = ∑ i = 1 n y i ∏ j ≠ i x − x j x i − x j   (   m o d     M ) f(x) = \sum_{i = 1}^n y_i\prod_{j \ne i} \frac{x - x_j}{x_i - x_j}~(\bmod~M) f(x)=i=1nyij=ixixjxxj (mod M),它在模意义下是唯一的。

(实际上有另外的证明方式证明了其在通常意义下也是唯一的,这里略去。)

本题中,我们只需要代入 k k k 求解即可,时间复杂度为 O ( n 2 ) \mathcal{O}(n^2) O(n2)。不过更多时候,我们需要求出其所有系数,也可以做到 O ( n 2 ) \mathcal{O}(n^2) O(n2),甚至还存在更低的复杂度,这里就不展开介绍了。

代码就不贴了。


多项式乘法

多项式乘法的定义,这里就不必多言了,初中数学都讲过。

代数形式:

设有多项式 f ( x ) = a 0 + a 1 x + a 2 x 2 + ⋯ + a n x n f(x) = a_0 + a_1 x+ a_2x^2 + \cdots+ a_nx_n f(x)=a0+a1x+a2x2++anxn g ( x ) = b 0 + b 1 x + b 2 x 2 + ⋯ + b m x m g(x) = b_0 + b_1 x+ b_2x^2 + \cdots+ b_mx_m g(x)=b0+b1x+b2x2++bmxm

则它们的乘法积为 t ( x ) = c 0 + c 1 x + c 2 x 2 + ⋯ + c n + m x n + m t(x) = c_0 + c_1 x + c_2 x^2 + \cdots +c_{n + m}x^{n + m} t(x)=c0+c1x+c2x2++cn+mxn+m

其中,对于 t ( x ) t(x) t(x) 的系数 c k c_k ck 有公式: c k = ∑ i = 0 k a i b k − i c_k = \sum_{i = 0}^k a_i b_{k - i} ck=i=0kaibki

可以发现这个公式的形式十分类似卷积。但请注意:它们不是同一个东西,不要弄混淆了。

事实上,多项式乘法就是用于求卷积的。如果您对卷积感兴趣,建议百度。


现在,给出两个多项式 f ( x ) f(x) f(x) g ( x ) g(x) g(x) 的系数,求出它们的乘法积 t ( x ) t(x) t(x) f ( x ) f(x) f(x) g ( x ) g(x) g(x) 的次数小于 1 0 5 10^5 105

根据上面的公式,我们可以得到一个 O ( n 2 ) \mathcal{O}(n^2) O(n2)优秀算法。

我们考虑换一种思想计算这个乘法积。

众所周知,有这样一条著名的定理:任意 k k k 个点可以唯一确定一个至多为 k − 1 k - 1 k1 次的多项式。

所以我们得到了一个新的思路:先求出足够多的 f ( x ) f(x) f(x) g ( x ) g(x) g(x) 的点值,将它们用 O ( n ) \mathcal{O}(n) O(n) 的复杂度乘起来(横坐标不变,纵坐标相乘),再将这些点转化为一个多项式(上面提到了这样的过程叫做插值)。

这种方法叫做离散傅里叶变换(即著名的 DFT ⁡ \operatorname{DFT} DFT)。

问题是,如果钦定一些 x x x 去求对应的 f ( x ) f(x) f(x) 的值,时间复杂度还是 O ( n 2 ) \mathcal{O}(n^2) O(n2) 的。

所以,下面介绍快速傅里叶变换,同时会介绍快速数论变换(即著名的 FFT ⁡ \operatorname{FFT} FFT NTT ⁡ \operatorname{NTT} NTT)。


前置知识:单位根原根

还记得二次函数 y = x 2 y = x^2 y=x2 的性质吗?

它关于 y y y 轴对称,所以我们如果代入 x = k x = k x=k,同样可以得到 x = − k x = -k x=k y y y 的值。

这启发我们,可以选取一些特殊的 x x x,使得我们可以在求出一些点值的同时,快速地求出另外的一些点值

这个时候,单位根就派上用场了。

先讲一些使得单位根能够应用于此的性质:

  1. ω n \omega_n ωn n n n 次单位根,即满足 ω n k = e 2 k π i n \omega_n^k = e^{\frac{2k\pi i}{n}} ωnk=en2kπi,而 e 2 k π i n = cos ⁡ 2 k π n + i sin ⁡ 2 k π n e^{\frac{2k\pi i}{n}}=\cos \frac{2k\pi}{n} + i \sin \frac{2k\pi}{n} en2kπi=cosn2kπ+isinn2kπ i i i 为虚数单位。

(注意 n n n 次单位根的 n n n 一般取 2 2 2 的正整数次幂,而下文皆如此。)

这个计算公式不仅可以让我们计算出单位根的具体数值,并且可以得出以下性质:

  • ω n n = cos ⁡ 2 π + i sin ⁡ 2 π = 1 = ω n 0 \omega_n^n = \cos 2\pi + i \sin 2\pi = 1 = \omega_n^0 ωnn=cos2π+isin2π=1=ωn0

这条性质说明 n n n 次单位根存在长度为 n n n 的指数循环节;

  • ω n n 2 = cos ⁡ π + i sin ⁡ π = − 1 \omega_n^{\frac{n}{2}} = \cos \pi + i \sin \pi= -1 ωn2n=cosπ+isinπ=1

这条性质间接地证明了 n n n 次单位根的最小指数循环节长度为 n n n,同时为下文折半引理的证明做了铺垫。

  1. 单位根消去引理: ω 2 n 2 k = ω n k \omega_{2n}^{2k} = \omega_n^k ω2n2k=ωnk

根据公式有 ω 2 n 2 k = e 4 k π i 2 n = e 2 k π i n = ω n k \omega_{2n}^{2k}= e^{\frac{4k\pi i}{2n}} = e^{\frac{2k\pi i}{n}} = \omega_{n}^k ω2n2k=e2n4kπi=en2kπi=ωnk,得证。

这条性质可以做为沟通不同次单位根的桥梁,同时也证明了 n n n 次单位根的值域是 2 n 2n 2n 次单位根值域的真子集

  1. 单位根折半引理: ω n k + n 2 = − ω n k \omega_n^{k+\frac{n}{2}} = -\omega_{n}^k ωnk+2n=ωnk

根据上面的性质有 ω n k + n 2 = ω n k ⋅ ω n n 2 = − ω n k \omega_n^{k + \frac{n}{2}} = \omega_n^k \cdot \omega_n^{\frac{n}{2}} = -\omega_n^k ωnk+2n=ωnkωn2n=ωnk,得证。

这条性质可以做为沟通同次不同指数的单位根的桥梁,为 DFT ⁡ \operatorname{DFT} DFT分治优化创造了可能。

而我们该如何运用单位根的这些性质呢?

我们将 f ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 f(x) = a_0 + a_1 x + a_2 x^2 + a_3x^3 f(x)=a0+a1x+a2x2+a3x3 做一个小小的改动:
f ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 = a 0 + a 2 x 2 + a 1 x + a 3 x 3 = ( a 0 + a 2 x 2 ) + x ( a 1 + a 3 x 2 ) = f 1 ( x 2 ) + x f 2 ( x 2 ) \begin{aligned} f(x) &= a_0 + a_1 x + a_2 x^2 + a_3x^3 \\ &=a_0 + a_2 x^2 + a_1 x + a_3x^3 \\ &= (a_0 + a_2 x^2) + x(a_1 + a_3 x^2) \\ &= f_1(x^2) + xf_2(x^2) \end{aligned} f(x)=a0+a1x+a2x2+a3x3=a0+a2x2+a1x+a3x3=(a0+a2x2)+x(a1+a3x2)=f1(x2)+xf2(x2)
可以发现,这样的变换,会使得原多项式被拆分为两个规模缩小了一半多项式

所以,我们又有了一个新的算法模型:

我们考虑将 f ( x ) f(x) f(x) 拆分为两个规模缩小了一半的多项式 f 1 ( x ) , f 2 ( x ) f_1(x), f_2(x) f1(x),f2(x),然后对它们进行分治,接着,我们可以用 f 1 ( x ) , f 2 ( x ) f_1(x),f_2(x) f1(x),f2(x) x = k 2 x = k^2 x=k2 处的点值计算出 f ( x ) f(x) f(x) x = k x = k x=k 处的点值。如果分治时每一层的复杂度都能够做到 O ( n ) \mathcal{O}(n) O(n),那么总的时间复杂度就是 O ( n log ⁡ 2 n ) \mathcal{O}(n \log_2 n) O(nlog2n)

接下来,我们考虑利用单位根的性质,将每一层转化点值的操作复杂度变为 O ( n ) \mathcal{O}(n) O(n)

如果我们将单位根 ω n k \omega_{n}^k

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值