快速傅里叶变换FFT
快速傅里叶变换FFT
作为我5.1出来培训这几天的原因,学会了之后当然要记录一下awa
虽然这是我唯一学会的内容qwq
首先,FFT是干什么的:
如果有这么两个东西:
$ A( x ) = \sum \limits_{i=0}^{n-1} a_i x^i $
$ B( x ) = \sum \limits_{i=0}^{n-1} b_i x^i $
让你求出 $ A(x)*B(x) $
啊,我会我会!直接 $ n^2 $ 枚举,进行多项式乘法就好了awa
是的,但是如果 $ n<=1e6 $ 呢?
你会发现 $ n^2 $ 就解决不了了,而且,枚举的方法显然已经无法继续优化了,所以我们需要另辟蹊径。
首先我们设 $ C(x) = A(x) * B(x) $
然后如果我们能快速的求出 $ A(x) $ 和 $ B(x) $ 的点值,那么我们就可以把他们乘在一起,之后就可以得到 $ C(x) $ 的点值,然后就可以逆向唯一确定 $ C(x) $ 的表达式了
(原理:n 次多项式唯一的由 n + 1 个不同点的值确定。)
(求点值就是随便带入一个 $ x $ ,然后求出它在函数图像上的 $ y $)
所以FFT就是干这个的:
(分为以下三步)
1.快速求出 $ A(x) $ 和 $ B(x) $ 的点值。(DFT)
2.将求出的 $ A(x) $ 和 $ B(x) $ 相乘
3.通过得到的 $ C(x) $ 的 $ n $ 个点值求出 $ C(x) $ 的 $ n $ 个系数 (IDFT)
(可以发现第三步求出的数就是答案)
开始求解:
我们可以记单位根 $ \omega_n = e^{\frac{{2 \pi i}}{n}} $
( $ i $ 就是虚数,一般为 $ \sqrt{-1} $ )
(选择 $ e^{\frac{2 \pi i}{n}} $ 的原因是 $ e^{2 \pi i} = 1 $ ,一会方便计算awa)
那么我们就可以将选的 $ n $ 个点值设定为:
$ x = \omega_n^{0} , \omega_n^{1} , \omega_n^{2} …… \omega_n^{n-1} $
之后我们将 $ A(x) = \sum \limits_{i=0}^{n-1} a_i x^i $ 拆成 $ A_1 (x^2) + x A_2(x^2) $
其中:
$ A_1(x) = a_0 + a_2 x + a_4 x^2 + …… + a_{n-2} x^{ \frac{n}{2} -1}$
$ A_2(x) = a_1 + a_3 x + a_5 x^2 + …… + a_{n-1} x^{ \frac{n}{2} -1}$
那我们再把我们设的 $ x = \omega_n^{k} $ 带入:
\(A(\omega_n^{k}) = A_1((\omega_n^{k})^2) + \omega_n^{k} A_2((\omega_n^{k})^2)\)
$ = A_1((e^{\frac{{2 \pi i * 2}}{n}})^k) + \omega_n^{k} A_2((e^{\frac{{2 \pi i * 2}}{n}})^k) $
$ = A_1((e^{\frac{{2 \pi i}}{ \frac{n}{2} }})^k) + \omega_n^{k} A_2((e^{\frac{{2 \pi i}}{ \frac{n}{2} }})^k) $
$ = A_1(\omega_{\frac{n}{2}}^k) + \omega_n^{k} A_2(\omega_{\frac{n}{2}}^{k}) $
因为我们设的是$ x = \omega_n^{0} , \omega_n^{1} , \omega_n^{2} …… \omega_n^{n-1} $,所以当 $ \omega_i $ 是 $ \frac{n}{2} $ 阶的时候, $ k $ 一定是小于 $ \frac{n}{2} $ 的,所以这只是前一半。
然后对于另一半,我们可以带入带入 $ x = \omega_n^{k+\frac{n}{2}} $ ,可以得出:
\(A(\omega_n^{k+\frac{n}{2}}) = A_1((\omega_n^{k})^2 * \omega_n^{n}) + \omega_n^{k+\frac{n}{2}} A_2((\omega_n^{k})^2 * \omega_n^{n})\)
$ = A_1((e^{\frac{{2 \pi i * 2}}{n}})^k * 1) + \omega_n^{\frac{n}{2}} * \omega_n^{k} A_2((e^{\frac{{2 \pi i * 2}}{n}})^k * 1 ) $
$ = A_1((e^{\frac{{2 \pi i}}{ \frac{n}{2} }})^k) - \omega_n^{k} A_2((e^{\frac{{2 \pi i}}{ \frac{n}{2} }})^k) $
$ = A_1(\omega_{\frac{n}{2}}^k) - \omega_n^{k} A_2(\omega_{\frac{n}{2}}^{k}) $
也就是说,如果我们已经求出了 $ A_1, A_2 $ 在阶为 $ \frac{n}{2} $ 时,某个单位根的点值,那么我们可以通过 $ O(n) $ 计算出 $ A(x) $ 在阶为 $ n $ 时,相应单位根的点值。
然后一直递归下去,当 $ n=1 $ 时,$ \omega_1 = e^{\frac{{2 \pi i}}{1}} = e^{2 \pi i} =1 $ 。答案就是 $ A(x) $ 的系数,然后我们再一层一层的返回,就可以求出最终答案。
这样就会发现,复杂度就是 $ T(n) = 2T(n/2) + O(n) = O(n log n) $ 的 $ awa $
然后我们发现当上式可做时,最好需要 $ n=2^k $ , 那我们就不妨让 $ n=2^k $ ,然后多出来的位数就让它的系数为 $ 0 $ 就好了。
所以我们就通过分治的方法,在 $ O(log n) $ 的时间内,解决了第一步(DFT)$ awa $
之后我们就分别对 $ A(x) $ 和 $ B(x) $ 求一遍,再将它们对应的点值相乘,就求出了 $ C(x) $ 的点值( 复杂度: $ O(n) $ )
第二步解决awa
然后是第三步。
乍一看第三步十分的困难 $ qwq $ ,但是我们从另一个角度去看第一步(DFT)
可以发现:我们实际上是把一个单位根矩阵 $ M=[\omega^{ij}] $ 左乘在了系数向量上, 那么实现 IDFT 实际上我们需要找到这个单位根矩阵的逆。
(上面一句一听就不是人话,让我们来形象的翻译一下)
首先,我们可以发现, $ DFT $ 其实干了下面这个事情:
对应上面的:“我们实际上是把一个单位根矩阵 $ M=[\omega^{ij}] $ 左乘在了系数向量上”
只不过我们用了一些比较魔幻的方法将它加速到了 $ O(nlogn) $ $ awa $。
为了方便表示,我们设:
相应的,$ M_c $ 和 $ M_C $ 同理
然后现在的情况是我们通过某些奇妙的方法求出了 $ M_C $ ,并且我们已经知道了 $ M_{\omega} $ 然后现在我们就是要求出 $ M_c $ 。
怎么求呢 $ qwq ? $
可以发现其实就是在 $ M_C $ 上乘上 $ M_{\omega} $ 的逆矩阵(不知道为什么的可以先去学一下矩阵相关的芝士)
我们先设 $ M_{\omega} '$ 为 $ M_{\omega} $ 的逆矩阵。
那么 $ M_{\omega}' $ 是什么呢?
我们先来浅猜一手:
$ M_{\omega} '= [ \omega^{-ij}]$
(就是把 $ M_{\omega} $ 的每一项的次数都 $ \times (-1) $ )
然后我们发现 $ M_{\omega} \times M_{\omega}' =n\times I_0 $
( $ I_0 $ 就是单位矩阵,即除了对角线是 $ 1 $ ,其他都是 $ 0 $ 该不会有人不知道吧awa )
所以我们就找到了 $ M_{\omega} $ 的逆矩阵 $ M_{\omega} '= [ \frac{\omega^{-ij}}{n}]$
第三步解……
Q:哎!不对!!还没解决呢!!!
Q:你这样进行矩阵乘法,不就是 $ O(n^2) $ 的了吗?
Q:你这复杂的有问题啊。
不不不,我们可以发现,其实 $ IDFT $ 就是把 $ DFT $ 里面的 $ M_{\omega} $ 换成了 $ M_{\omega}' $ , $ M_a $ 换成了 $ M_C $
其他的没有任何的改变。
所以可以如法炮制,直接向上面一样 $ O(n log n) $ 解决 $ awa $
所以第三步(\(IDFT\))解决.

浙公网安备 33010602011771号