FFT

问题描述

给定 \(n\),有 \(a_{0\sim 2^n-1}\)\(b_{0\sim 2^n-1}\),求出 \(c_{0\sim 2^n-1}\),满足

\[c_z=\sum_{z=(x+y)\bmod 2^n} a_xb_y \]

记其为 \(c=a\ast b\)

符号 和 约定

假定序列的下标从 \(0\) 开始

\(\omega_n^x=e^{\frac{2\pi xi}{2^n}}=\cos \frac{2\pi xi}{2^n}+i\sin \frac{2\pi xi}{2^n}\) 表示单位根

\(|a|\) 表示序列 \(a\) 的长度

\(A_a(x)=\sum_{i=0}^{|a|-1} a_ix^i\)\(L(a)\)\(a\) 的偶数下标形成的子序列,\(R(a)\)\(a\) 的奇数下标形成的子序列

\(\text{FFT}_n(a)\) 表示长为 \(2^n\) 的序列 \(a\) 经过 \(\text{FFT}\) 变换的结果,\(\text{FFT}^{-1}_n(a)\) 表示长为 \(2^n\) 的序列 \(a\) 经过 \(\text{IFFT}\) 变换的结果,两者互为逆变换,即 \(\text{FFT}_n(\text{FFT}^{-1}_n(a))=\text{FFT}^{-1}_n(\text{FFT}_n(a))=a\)

\(a\cdot b\) 表示数组 \(a\)\(b\) 逐项相乘的结果

基本思想

\(\text{FFT}_n(a)_k=A_a(\omega_n^k)\),可证此时对应的 \(\text{IFFT}\)\(\text{FFT}\) 的基础上进行少量额外操作,而 \(\text{FFT}\) 可以用单位根的性质分治优化

由于

\[c=a\ast b=\text{FFT}^{-1}(\text{FFT}(a)\cdot \text{FFT}(b)) \]

可证 \(\text{FFT}^{-1}(\text{FFT}(a)\cdot \text{FFT}(b))\) 的虚部必为 \(0\)

中间的 \(\cdot\) 运算为 \(O(n)\) 的,因此若能在优于 \(O(n^2)\) 的时间复杂度内实现 \(\text{FFT}\)\(\text{FFT}^{-1}\),则能优化 \(c=a\ast b\) 的过程

FFT

\[\begin{aligned} \text{FFT}_n(a)_k=&A_a(\omega_n^k)\\ =&\sum_{i=0}^{2^n-1}a_i(\omega_n^k)^i\\ =&\sum_{i=0}^{2^n-1}[i\equiv 0\pmod 2]a_i(\omega_n^k)^i+\sum_{i=0}^{2^n-1}[i\equiv 1\pmod 2]a_i(\omega_n^k)^i\\ =&\sum_{i=0}^{2^{n-1}-1}a_{2i}\omega_n^{2ik}+\sum_{i=0}^{2^{n-1}-1}a_{2i+1}\omega_n^{2ik+k}\\ =&\sum_{i=0}^{2^{n-1}-1}L(a)_i(\omega_{n-1}^k)^i+\omega_n^k\sum_{i=0}^{2^{n-1}-1}R(a)_i(\omega_{n-1}^k)^i\\ =&A_{L(a)}(\omega_{n-1}^k)+\omega_n^kA_{R(a)}(\omega_{n-1}^k) \end{aligned} \]

对于 \(k<2^{n-1}\),有

\[\begin{aligned} \text{FFT}_n(a)_k=&A_{L(a)}(\omega_{n-1}^k)+\omega_n^kA_{R(a)}(\omega_{n-1}^k)\\ =&\text{FFT}_{n-1}(L(a))_k+\omega_n^k\text{FFT}_{n-1}(R(a))_k\\ \end{aligned} \]

对于 \(k\ge 2^{n-1}\),有

\[\begin{aligned} \text{FFT}_n(a)_k=&A_{L(a)}(\omega_{n-1}^k)+\omega_n^kA_{R(a)}(\omega_{n-1}^k)\\ =&A_{L(a)}(\omega_{n-1}^{k-2^{n-1}})+\omega_n^kA_{R(a)}(\omega_{n-1}^{k-2^{n-1}})\\ =&\text{FFT}_{n-1}(L(a))_{k-2^{n-1}}+\omega_n^k\text{FFT}_{n-1}(R(a))_{k-2^{n-1}}\\ \end{aligned} \]

对于一个 \(k<2^{n-1}\),考虑 \(\text{FFT}_n(a)_k\)\(\text{FFT}_n(a)_{k+2^{n-1}}\),显然有

\[\text{FFT}_n(a)_k=\text{FFT}_{n-1}(L(a))_k+\omega_n^k\text{FFT}_{n-1}(R(a))_k\\ \text{FFT}_n(a)_{k+2^{n-1}}=\text{FFT}_{n-1}(L(a))_k-\omega_n^k\text{FFT}_{n-1}(R(a))_k\\ \]

据此可分治递归计算,时间复杂度 \(O(n\log n)\)

一般写为非递归形式

IFFT

主要有两种实现

第一种为令单位根为其倒数,进行一次 \(\text{FFT}\),然后全都除以 \(2^n\)

第二种为进行一次 \(\text{FFT}\) 后,全都除以 \(2^n\),然后翻转 \([1,2^n)\)

两者是等价的,时间复杂度都是 \(O(n\log n)\)

性质

\(\text{FFT}\) 为线性变换

优化

假如连续进行多次 \(\ast\) 运算,则可以把所有数组都先进行一次 \(\text{FFT}\),逐项相乘后再进行一次 \(\text{IFFT}\),从而减小常数

对于两项相乘的情况,有一个常用的三次变两次优化:

朴素 \(\text{FFT}\) 为两次正变换和一次负变换,实际上可以优化到一次正变换和一次负变换

复数数组 \(v\)\(\text{Real}(v_i)=a_i,\text{Imag}(v_i)_i\),则 \(c_i=2^{-n-1}\text{Imag}(\text{FFT}^{-1}_n(\text{FFT}_n(v)\cdot \text{FFT}_n(v)))\)

但是这种方法的误差大于朴素 \(\text{FFT}\),需要注意

posted @ 2025-04-24 07:34  Hstry  阅读(3)  评论(0)    收藏  举报