快速数论变换_快速傅立叶变换(FFT)

本文详细介绍了快速傅立叶变换(FFT)在优化多项式乘法中的应用。首先,定义了多项式及其系数表达和点值表达,接着探讨了DFT(离散傅立叶变换)及其逆变换,指出通过单位复数根可以加速转化过程。最后,提到了快速数论变换(NTT)作为FFT的一种优化,实现了更高效的多项式运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

770ea0f3e25e1fb40b6dd8452835fc5c.png
  • 快速傅立叶变换用于优化多项式乘法.

多项式

  • 一个以
    为变量的
    多项式定义在一个代数域
    上,将多项式
    表示为形式和:

  • 称为多项式的
    系数,若一个多项式最高次非零的系数为
    ,则称
    次数
    ,记作
    . 并称任何一个严格大于多项式次数的整数为该多项式的
    次数界. 可以发现其实一个次数界为
    的多项式可以由一个向量
    表示,称此为多项式的
    系数表达.
  • 对于两个多项式(
    )的乘法:

其中,

,由此式推导出的向量
称为输入向量
卷积,记作
.
  • 点值表达:利用线性代数知识可以知道,一个次数界为
    的多项式可以由
    个点值对组成的集合表示:

其中,

并且
.

DFT及其逆

  • 可以发现,虽然利用系数表达进行多项式乘法的时间复杂度为
    ,但是由于
    的次数界为
    ,所以多项式点值的乘法其实是
    的. 于是优化的方向在:能否快速的把系数表达转化成点值表达(求值),并将计算好的
    的点值快速转化为系数表达(插值).

复数

  • 我们知道满足
    的复数有
    个,并称
    为单位复数根,此外我们还将
    称为
    次单位根
    ,其他所有单位根均为其幂次,也就是可以将他们全部表示为:

其中,

.
  • 消去引理:对任何整数
    ,以及
    ,均有

  • 折半引理:如果
    为偶数,那么
    次单位根的平方的集合恰好是
    次单位根的集合.(在此我们假设
    的幂次.)

    由于
    ,且
    即证.
  • 求和引理:对于
    ,均有

DFT

  • 可以发现点值表示时的点其实是可以任意选取的,我们希望通过选取合适的点来加速这一过程.
  • 观察多项式
    ,如果将奇偶项分别提取出来:

这么一来可以发现

的幂次都是偶数,或者这么写

这样以来就有

.

我们惊奇地发现这里的

其实是规模为原来一半的多项式求值. 如果注意到刚才的
折半定理,就可以发现如果取
个单位复数根,那么恰好
就恰好取得是
的单位复数根. 所以我们可以递归地去做,并且有

由此实现快速傅立叶变换(FFT).

逆DFT

  • 利用线性代数矩阵求逆可以知道:

注意到

所以我们只需要用

替换
然后进行快速傅立叶变换并最后将答案除以
即可.

由此实现逆FFT.

其他

  • 解决了
    的情况,对于任意的正整数
    ,只需要高位补零使其成为次数为
    的多项式即可.
  • 优化:利用蝴蝶操作将递归过程改为自底向上迭代过程.
  • 注意到原根也有单位复数根的性质,由此产生快速数论变换(NTT).
### 高精度乘法算法概述 高精度乘法是指用于计算超出常规整数表示范围的大数值之间的乘积的一类算法。这类算法不仅解决了传统计算机硬件对于大数运算能力有限的问题,同时也提高了计算效率。 #### 基础方法——长乘法/列乘法 一种基础且直观的方式是模拟人们日常使用的纸笔乘法规则,即所谓的“长乘法”或“列乘法”。这种方法基于手工乘法的过程,在程序设计中通过循环结构来完成多位数间的逐位相乘操作,并妥善处理每次相乘产生的进位情况[^1]。 ```python def multiply_long_form(num1, num2): result = [0] * (len(num1) + len(num2)) for i in reversed(range(len(num1))): for j in reversed(range(len(num2))): mul = int(num1[i]) * int(num2[j]) p1, p2 = i + j, i + j + 1 sum_ = mul + result[p2] result[p1] += sum_ // 10 result[p2] = sum_ % 10 while len(result) > 1 and not result[0]: del result[0] return ''.join(map(str, result)) or '0' ``` 此代码片段展示了如何利用Python实现两个字符串形式的大数之间按位相乘并考虑进位逻辑的函数`multiply_long_form()`。 #### 进阶优化方案 随着研究深入和技术发展,出现了多种更高效的高精度乘法策略: - **分治乘法**:采用递归方式减少所需执行的基本乘法次数,典型代表为Karatsuba算法以及其扩展版本Toom-Cook算法; - **快速傅立叶变换(FFT)** 或者改进版 快速数论变换(FNTT),能够显著降低多项式卷积的时间复杂度至 O(n log n),适用于非常庞大的数字相乘场景; - **中国剩余定理(CRT)** 方法则是借助于模运算特性来进行间接求解,特别适合特定条件下加速计算过程; 上述提到的不同类型的高级技术均能在不同程度上提升性能表现,但具体应用时需综合考量实际需求与资源消耗等因素作出合理选择[^2]。 #### Java中的实践案例 针对Java编程环境下的大数相乘问题,有一种常见的解决方案就是采取逐位相乘再处理进位的办法。这种方式下,会先将参与运算的数据逆序存储在一个数组之中,之后按照位置关系依次配对相乘得到临时结果集,最后调整这些中间产物的位置并通过累加以获得最终答案[^3]。 ```java public class BigIntegerMultiplication { public static String bigIntegerMultiply(String number1, String number2){ if(number1.equals("0") || number2.equals("0")) return "0"; int[] pos = new int[number1.length() + number2.length()]; for(int i=number1.length()-1; i>=0 ;i--){ for(int j=number2.length()-1;j>=0;j--){ int multi = (number1.charAt(i)-'0')*(number2.charAt(j)-'0'); int p1=i+j; int p2=p1+1; int sum = multi + pos[p2]; pos[p1]+=sum / 10; pos[p2]=sum%10; } } StringBuilder sb=new StringBuilder(); boolean flag=false; for(int val :pos){ if(val!=0||flag==true){ sb.append(val); flag=true; } } return sb.toString().equals("")?"0":sb.toString(); } } ``` 这段Java代码实现了类似的逐位相乘机制,其中包含了必要的边界条件判断和零值特判部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值