多项式学习笔记

啊?

“做多项式题就像ke药,出多项式题就像fan毒。” —— 可爱小粉兔

“以快速傅里叶变换为基石的多项式算法赋予了算法竞赛选手直接操纵生成函数的能力。”—— 摘自 OI-wiki

FFT 与 NTT

在多项式题目中,使用快速傅里叶变换、快速数论变换来加速运算或卷积是十分常见的。

它们能通过分治来加速卷积是运用到了复数和原根的奇妙特性。

n 次多项式 AB 相乘的积时,我们可以代入点插值后直接乘法计算再转换。(当然也可以直接算)

可是计算一个点值的时间是 O(n) 的,n+1 个点复杂度就是 O(n2)

转换成多项式的拉格朗日插值也是 O(n2) 的。f(k)=i=0nyijikxjxixj

而离散傅里叶变换可以在 O(nlog2n) 时间内解决问题(DFT, IDFT)。

这就需要一些多项式推导和分治思想。

O(log2n) 层递归,每层花 O(n) 时间处理。

复数 与 原根

首先是复数。

可以发现单位复根在坐标系中的半径为 1 的圆上。记方程 xn=1 的第 k 个根为 ωnk(从 0 开始,可以看作模 n 的同余系来理解)

算法的基本思想是分治。分治求当 x=ωnk 的时候 f(x) 的值。

举个例子,对于一共 8 项的多项式:

f(x)=a0+a1x+a2x2+a3x3+a4x4+a5x5+a6x6+a7x7

按照次数的奇偶来分成两组,然后右边提出来一个 x

f(x)=(a0+a2x2+a4x4+a6x6)+(a1x+a3x3+a5x5+a7x7)=(a0+a2x2+a4x4+a6x6)+x(a1+a3x2+a5x4+a7x6)

分别用奇偶次次项数建立新的函数:

G(x)=a0+a2x+a4x2+a6x3H(x)=a1+a3x+a5x2+a7x3

那么原来的 f(x) 用新函数表示为:

f(x)=G(x2)+x×H(x2)

到目前为止可能还无法瞥见单位复根的作用,其实单位复根在这里是这样的:

利用 ωni=ωni+n/2,和 G(x2)H(x2) 是偶函数(显然):

可以知道在复平面上 ωniωni+n/2G(x2)H(x2) 对应的值相同。

得到:

f(ωnk)=G((ωnk)2)+ωnk×H((ωnk)2)=G(ωn2k)+ωnk×H(ωn2k)=G(ωn/2k)+ωnk×H(ωn/2k)

和:

f(ωnk+n/2)=G(ωn2k+n)+ωnk+n/2×H(ωn2k+n)=G(ωn2k)ωnk×H(ωn2k)=G(ωn/2k)ωnk×H(ωn/2k)

一加一减。

因此我们求出了 G(ωn/2k)H(ωn/2k) 后,就可以同时求出 f(ωnk)f(ωnk+n/2)。于是对 GH 分别递归 DFT 即可。

只有复数域中才能构造出这样美丽的值代入。

这样就省去了一半的计算量,递归下去算出一个点就只需要 O(log2n) 次操作了。

一般 FFT 都是直接分治操作,用蝴蝶变换算出位置减少常数。

原根怎么你了?

NTT 解决的是多项式乘法带模数的情况,可以说有些受模数的限制,数也比较大。目前最常见的模数是 998244353。(原根是 3,好吃)

由欧拉定理可知,对 aZmN,若 (a,m)=1,则 aφ(m)1(modm)

因此满足同余式 an1modm 的最小正整数 n 存在,这个 n 称作 am 的阶,记作 δm(a)

可以用阶类比平方。

原根

mNgZ。 若 (g,m)=1,且 δm(g)=φ(m),则称 g 为模 m 的原根。

g 满足 δm(g)=|Zm|=φ(m)

m 是质数时,我们有 gimodm,0<i<m 的结果互不相同。

从这里就可以看出,原根很像单位复根。

例如 m=998244353 时,就有

数论变换(NTT)是通过将离散傅立叶变换化为 F=Z/p,整数模质数 p。这是一个有限域,只要 p1 可被 n 整除,就存在本原 n 次方根,所以对于正整数 ξ 我们有 p=ξn+1

具体来说,对于质数 p=qn+1,原根 g 满足 gqn1modp, 将 gn:=gqmodp 看做 ωn 的等价,则其满足相似的性质。

比如 gnn1modp 就有对应的 gnn/21modp

因为有:p=998244353=7×17×223+1,g=3

所以用 998244353 做模数时可以方便的将 n 补到 2 的幂,然后推出 q=p1n,以构造出和单位复根性质相同的东西。(223=8388608 完全够用)

FFT 改一改就是 NTT 了。

多项式基础

多项式取模,多项式求逆,多项式除法,多项式开根,多项式快速幂,多项式ln

这些东西都别急。

分治 FFT/NTT

例题:现有一转移式形如 f(i)=j=0i1f(j)g(ij),其中终止条件 f(0)=1,给定 g(i)f(i),对 998244353 取模。

首先直接算 fn 需要 n1 次操作,总共时间是 O(n2) 的,考虑怎么优化卷积。

发现 f 的第推式是前项对 g 的卷积,不能一次性求出。

可以使用分治,将 f 值域中左半区间对右半区间的贡献提前累加到右半区间。

具体的,设左为 [l,mid] 右为 [mid+1,r] 且有一点 k 满足 k[mid,r],考虑左区间对 f(k) 的贡献。

则有 vk=j=lmidf(j)g(kj)

其中 f(j)g(ij) 是一个卷积的形式(而且没有那丑陋的第推式了),所以可以直接把 flmidg0rl 提出来,对这一部分进行 NTT

所以左边对右边的所有点的贡献均可以在一次多项式乘法中得出。

用CDQ的形式,总复杂度 O(nlog2n)

生成函数

你先别急。

《具体数学》怎么你了?

在系统学习多项式之前我一直难以理解生成函数,不知道它的构造方法,含义以及用途。

生成函数(generating function),又称母函数,是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息。

posted @   RoFtaCD  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示

目录导航