FFT
FFT 流程
-
一个数字可以看成
,那么把两个数字转成多项式的形式,求最后每一项的系数 -
我们知道一个多项式可以通过
个系数,或者 个点值来确定,那么我们考虑快速的让两个多项式转换成点值表示,然后点值的值是可以直接乘起来的,然后再通过得到的 的 个点值转回系数 -
FFT 要求长度为
,所以不够的补 0
系数转点值
-
对于函数
-
-
设
-
那么
-
注意到这个
我们取单位根 ,之所以这个取是因为单位根是 在复数域下的解,幂次最后得出是 1 会方便我们计算 -
单位根有一些性质:
-
那么最后就会得到
-
可以发现中间的符号不同,其他都是一样的,那么我们只要递归求
和 就可以了 -
最后得到的函数的每一位是相应的点值
-
复杂度为
,递归写法
蝴蝶变换
-
观察发现编号为
的下标,最后会变到 的下标 -
这个可以预处理出来,将每个数变换到对应的地方,那么就可以直接递推处理
-
具体的变换可以参照
rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
点值转系数
-
实际上这个时候一般的高斯消元可以列出一个矩阵,具体可见 OI-Wiki
-
我们惊喜的发现这个系数矩阵是可逆的,并且逆矩阵的每个位置就是原来的数倒一下再除以 n
-
这个除以 n 可以放在最后再一起除
-
然后此时已经求出的点值乘上逆矩阵就等于原系数
-
我们将点值看成系数,系数看成新的点值,那么就转换成了之前的 快速系数转点值
-
因为只是倒一下,所以符号上有一点不同,其他的都是一样的
8 次MTT
-
FFT 的精度损失是一方面,另一方面无法像 NTT 那样做大值域,因为没办法取模
-
于是就有了拆系数 FFT ,也叫 MTT
-
以 P4245 【模板】任意模数多项式乘法 为例
-
一种方法是直接将一个函数
拆成 , -
-
那么
,那么就要做 8 次 FFT -
取 最好,开long double
信仰的跑,值域是解决了,但是常数巨大
4 次 MTT
-
首先还是像上面一样拆式子,那么现在有
四个系数式,我们希望通过 2 次 DFT 得到它们各自的点值 -
构造系数式
-
注意到
的每一项都共轭,那么它们的点值也共轭,那么我们求出 的点值,然后推出 的点值,然后类似于解一元二次方程来解出 -
那么分成两组,一共就是 2 次 DFT
-
现在得到了
的点值 -
更抽象的,现在有 4 个点值式
,我们希望通过 2 次 IDFT 得到它们两两乘积的系数式 -
构造
-
那么
-
通过 2 次 IDFT 可以得到上述式子
-
因为最终的答案不存在虚部,那么就可以通过虚部和实部分别解出
,正好符合我们的要求 -
那么总的就是要进行 4 次 FFT
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】