快速傅里叶变换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 $ 其实干了下面这个事情:

\[\begin{bmatrix} (\omega_n^{0})^{0} & (\omega_n^{0})^{1} & … & (\omega_n^{0})^{n-2} &(\omega_n^{0})^{n-1}\\ (\omega_n^{1})^{0} & (\omega_n^{1})^{1} & … & (\omega_n^{1})^{n-2} &(\omega_n^{1})^{n-1}\\ \vdots & & \ddots & & \vdots\\ (\omega_n^{n-2})^{0} & (\omega_n^{n-2})^{1} & … & (\omega_n^{n-2})^{n-2} &(\omega_n^{n-2})^{n-1}\\ (\omega_n^{n-1})^{0} & (\omega_n^{n-1})^{1} & … & (\omega_n^{n-1})^{n-2} &(\omega_n^{n-1})^{n-1}\\ \end{bmatrix} \times \begin{bmatrix} a_0\\ a_1\\ \vdots\\ a_{n-2}\\ a_{n-1}\\ \end{bmatrix} = \begin{bmatrix} A(\omega_n^0)\\ A(\omega_n^1)\\ \vdots\\ A(\omega_n^{n-2})\\ A(\omega_n^{n-1})\\ \end{bmatrix} \]

对应上面的:“我们实际上是把一个单位根矩阵 $ M=[\omega^{ij}] $ 左乘在了系数向量上”

只不过我们用了一些比较魔幻的方法将它加速到了 $ O(nlogn) $ $ awa $。

为了方便表示,我们设:

\[ M_{\omega} =\begin{bmatrix} (\omega_n^{0})^{0} & (\omega_n^{0})^{1} & … & (\omega_n^{0})^{n-2} &(\omega_n^{0})^{n-1}\\ (\omega_n^{1})^{0} & (\omega_n^{1})^{1} & … & (\omega_n^{1})^{n-2} &(\omega_n^{1})^{n-1}\\ \vdots & & \ddots & & \vdots\\ (\omega_n^{n-2})^{0} & (\omega_n^{n-2})^{1} & … & (\omega_n^{n-2})^{n-2} &(\omega_n^{n-2})^{n-1}\\ (\omega_n^{n-1})^{0} & (\omega_n^{n-1})^{1} & … & (\omega_n^{n-1})^{n-2} &(\omega_n^{n-1})^{n-1}\\ \end{bmatrix} \]

\[M_a= \begin{bmatrix} a_0\\ a_1\\ \vdots\\ a_{n-2}\\ a_{n-1}\\ \end{bmatrix} \]

\[M_A= \begin{bmatrix} A(\omega_n^0)\\ A(\omega_n^1)\\ \vdots\\ A(\omega_n^{n-2})\\ A(\omega_n^{n-1})\\ \end{bmatrix} \]

相应的,$ 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\))解决.

所以,我宣布,FFT,搞定 $ awa $ !

posted @ 2024-07-11 14:51  YT0104  阅读(28)  评论(0)    收藏  举报