0%

NTT学习笔记

NTT 的中文名称为快速数论变换,英文全称为 Number-theoretic transform,是 FFT 在数论基础上的实现,可以避免 FFT 的复数运算中的精度损失。

NTT 实际上是将 FFT 中的复数运算巧妙的替换为了整数运算。

原根

若一个正整数 和一个质数 满足对于所有 , 的值互不相同。

NTT原理

实际上,NTT 就是选取了适当的模数以及任何一个这个质数的原根,并用一些整数代替了复数(被代替的就是上面的 )。

直接这样说估计没人懂,举个例子。

就以最常见的 NTT 模数 和它的原根(之一) 来举例。

首先一个比较重要的地方,就是 ,这是 NTT 模数的关键之一,这个模数减一必须是 的较大次幂的倍数。

假设现在要进行 NTT 的多项式共有 项(和 FFT 一样, 是 的整数次幂),那么用哪个数字代替 比较合适呢?

不难想到,用 代替 ,同理对于其他 ,用 代替 ,这样就大功告成。

此外将 FFT 的其他操作(加法,乘法,减法等)改成模意义下的运算,所有的复数都改成整数,就可以了。

同理,假如使用一个质数 与它的原根 进行 NTT 时,使用 代替 即可。

正确性证明

不难发现,FFT 能够快速运算的运算在于复数的那三个性质。

同时,这也是 NTT 可以快速计算的关键,因为我们刚刚对于 的取值也满足这些性质!

下面我们来一条一条看。 证明: 注意,对于所有质数 都有 。


证明:


证明: 就是要证

注意到一定会有

所以这个式子的值为 。

额, 似乎不算很显然,我们来证一下。

首先,根据原根的性质,我们知道对于 ,肯定恰好存在一个 使得 。

那么我们就知道,一定会有 。

同时,我们知道,一定恰好存在一个 使得 (还是原根的性质),而我们知道 。

所以就会有 。

这个方程一共有两个解, 或 。

显然, 不满足条件,因为 。

所以一定会有 。

NTT 就说完了。

提交记录

加上快读和快写还能快一点。


下面是几个模板呀。

多项式求逆

P4238 【模板】多项式乘法逆

设原多项式为 ,它的逆为 。

设 ,它的逆为 。

则一定会有以下几个性质: 则由 可得: 两边同时乘上 。(其实只有一边) 也就是说,只要我们知道了 ,就可以在 的时间内把 算出来(NTT 把上面的式子卷一下)。

时间复杂度 。

提交记录

任意模数多项式乘法

P4245 【模板】任意模数多项式乘法

我们可以发现,这道题里面的模数可能不能满足之前我们对模数的要求,甚至不是一个质数,所以我们不能直接进行 NTT。

这里我使用的是三模数 NTT。

具体做法就是我们找三个可以进行的 NTT 的模数,然后做三遍 NTT,最后使用 CRT 求出答案。

这里我使用的三个模数分别为 ,,。

直接做就可以了。

然而最后的 CRT 还是有一些细节的(),因为模数个数比较少,所以我们可以手颓柿子:

首先我们知道这些:

所以一定存在三个自然数 使得 。 这样我们就可以求出 的值了,不妨记作 。 令 ,则存在 使得 。 和 都知道了,我们就可以求出 了。

当然,你也可以使用 __int128来做。

中间的取模还是有很多细节的,具体可以看代码。

提交记录

把三个数字写成一个结构体,一起 NTT 还能更快亿点,真的是亿点。

提交记录

分治NTT

P4721 【模板】分治 FFT

虽然写的是 FFT,但实际上是分治 NTT...

我们要求出一个满足条件的多项式 ,但是 的值和 有关。

考虑进行分治。

假设我们现在分治到了一个区间 ,下一步肯定是分治 这个区间。

然后呢?我们需要快速处理区间 向 的贡献。

实际上 NTT 卷一下就可以了。

时间复杂度 。

提交记录

例题

hdu7162 和 题解