比FFT还容易明白的NTT(快速数论变换)

NTT(快速数论变换)是一种用于加速多项式乘法的算法,尤其适合在模域中进行计算,因为它可以取模且避免了FFT的精度问题。NTT基于数论中的原根性质,其优点包括能进行模运算、无精度误差,但要求系数为整数且模数有限制。在计算过程中,原根代替了FFT中的单位根,时间复杂度为O(nlog2n)。学习NTT需要掌握原根等相关前置知识。
摘要由CSDN通过智能技术生成

NTT相关

一种快速数论变换算法,这种算法是以数论为基础,对样本点为的数论变换,按时间抽取的方法,得到一组等价的迭代方程,有效高速简化了方程中的计算公式·与直接计算相比,大大减少了运算次数。(见快速傅里叶变换)。
在计算机实现多项式乘法中,我们所熟知的快速傅里叶变换(FFT)是基于n次单位根 (omega) 的优秀性质实现的,而由于其计算时会使用正弦函数和余弦函数,在不断运算时无法避免地会产生精度误差。而多项式乘法有些时候会建立在模域中,在对一些特殊的大质数取模时,便可以考虑用原根g来代替 ,而这些特殊的大质数的原根恰好满足 的某些性质,这使得多项式乘法在模域中也可以快速的分治合并。
——百度百科

NTT(Number Theoretic Transform),中文名快速数论变换
F F T FFT FFT一样, N T T NTT NTT也用来加速多项式乘法,不过 N T T NTT NTT最大的优点是可以取模
或者可以理解为 N T T NTT NTT F F T FFT FFT取模升级版

  • 好像 N T T NTT NTT比起 F F T FFT FFT来难的知识点更少了emm

NTT的优缺点

优点

  • 能取模 F F T FFT FFT的复数你给我来取个模

  • 没有精度差 F F T FFT FFT浮点数的精度怎么也会出一点问题

  • 由于均为整数操作(虽然取模多), N T T NTT NTT常数小,通常比一大堆浮点运算的 F F T FFT FFT(其实这是放屁)

我只能说 N T T NTT NTT小数据下表现良好…

缺点

  • 多项式的系数都必须是整数

  • 模数有限制 N T T NTT NTT题的模数通常都是相同 998244353 998244353 998244353

  • 其实这些模数的原根通常都是 3 3 3


NTT前置知识&技能

原根

快速傅里叶变换(Fast Fourier Transform,FFT)是一种高效的算法,用于快速计算离散傅里叶变换(Discrete Fourier Transform,DFT)。它可以将一个序列转换为其频率分量。 在C语言中,实现快速FFT变换可以使用递归或迭代的方式。以下是一个用C语言实现快速FFT变换的简单示例: 首先,需要定义一个复数结构体,用来存储实部和虚部: ```c typedef struct { double real; double imag; } Complex; ``` 接下来,实现关键的FFT函数: ```c void fft(Complex arr[], int size, int inverse) { if (size <= 1) { return; } Complex even[size / 2]; Complex odd[size / 2]; // 分离奇数项和偶数项 for (int i = 0; i < size / 2; i++) { even[i] = arr[2 * i]; odd[i] = arr[2 * i + 1]; } // 递归计算奇数项和偶数项的FFT fft(even, size / 2, inverse); fft(odd, size / 2, inverse); // 计算每个频率分量 double angle = 2 * PI / size * (inverse ? -1 : 1); Complex w = {1, 0}; Complex wn = {cos(angle), sin(angle)}; for (int i = 0; i < size / 2; i++) { Complex temp = mult(w, odd[i]); arr[i] = add(even[i], temp); arr[i + size / 2] = sub(even[i], temp); if (inverse) { arr[i] = div(arr[i], 2); arr[i + size / 2] = div(arr[i + size / 2], 2); } w = mult(w, wn); } } ``` 其中,mult、add、sub和div是对复数进行乘法、加法、减法和除法的函数。 最后,在主函数中调用FFT函数: ```c int main() { Complex arr[N]; // 输入序列 // 初始化输入序列 // ... fft(arr, N, 0); // 进行正向FFT变换 // 输出频率分量 for (int i = 0; i < N; i++) { printf("%f + %fi\n", arr[i].real, arr[i].imag); } return 0; } ``` 这样就可以实现快速FFT变换的功能了。快速FFT变换在信号处理、图像处理以及其他科学和工程领域中都有广泛的应用。它通过减少计算量,大大提高了傅里叶变换的计算效率。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值