2.upd.2025.7.10
oi.polo.fft
快速傅里叶变换(Fast Fourier Transform)
FFT三问:
1.什么是FFT
- 一个快速处理卷积的算法
2.什么是卷积
- 就是多项式乘法
3.FFT有多快
- 常规卷积或是DFT时间复杂度为\(O(n^2)\),而FFT为\(O(nlog_2n)\),比常规卷积快了将近一阶
算法实现:
Chapter1: 首先我们先来看两种多项式的表示形式
1.记录系数
2.记录点
首先我们先来看1.记录系数:
假设我现在有一个多项式叫做\(P(x)\),它有\(n\)个系数(n项)
那么不难发现它代数形式肯定能写成:
\(P(x) = a_0 +a_1x+a_2x+...+a_{n-2}x^{n-2}+a_{n-1}x^{n-1}\)
因此我记录\(P(x)\)也只需要记录其系数\({\{a_n\}}\)序列
我们再来看2.记录点
我们都学过待定系数法
因此我们知道对于一个\(n\)次函数,我们只需要取\(n+1\)个点就可以求出这个函数的代数式了!
所以我们只要记录\(n\)个点就可以表示这个\(n\)项多项式\(P(x)\)了
Chapter2: 这两种存储方式该如何进行卷积运算?
1.记录系数方式的卷积:
很简单,我们直接用乘法分配律去算,但是对于两个项数为\(n\)的多项式,这样做的时间复杂度为\(O(n^2)\), 非常菜
2.记录点坐标方式的卷积:
设\(n\)阶多项式\(F(x)\)与\(m\)阶多项式\(G(x)\)相乘,结果为\(n+m\)阶多项式\(P(x)\) \(\Rightarrow\) \(P(x) = F(x)*G(x)\)
因此我们取\(F(x)\)和\(G(x)\)共\(n+m\)个点,将每一个点\((x_0,F(x))\)和\((x_0,G(x))\)相乘,得到\((x_0,F(x)*G(x)),这个点一定在P(x)上\)
但是我们发现取点需要\(O(n)\),计算需要\(O(n)\),总共还是要\(O(n^2)\),目前我们优化卷积还是毫无进展
Chapter3: 对于记录点坐标方式卷积的优化
假设我现在要对于\(F(x)=x^2+1\)取\(m\)个点,我们要怎么做呢
一种方法是直接简单的取m个点,如取\(x=1,2,3,...,m\),并分别计算\(F(x)\),需要算2*m次(2为F(x)的项数)
但是我们思考\(F(x)\)的性质,它是一个偶函数欸!
\(F(x) = F(-x)\)
因此如果我们取 \(\pm 1,\pm2\)这样,我们计算出\(F(x)\)就相当于计算出了\(F(-x)\)!,要算\(m\)次
同理,对于奇函数我们也是如此
但是万一我的函数非奇非偶呢???
给定多项式\(F(x)=a_0+a_1x+a_2x^2+...+a_{n-1}x^{n-1}+a_{n}x^{n}\),为方便讨论我们假设\(n\)为偶数
我们有什么办法给\(F(x)\)施加奇偶性呢?
我们按照\(x\)的次数分为两类:
\(F(x) = (a_0 +a_2x^2+a_4x^4+...+a_nx^n) + (a_1x+a_3x^3+...+a_{n-1}x^{n-1})\)
我们令\(F_{even}(x^2)=a_0+a_2x^2+a_4x^4 + ...+a_nx^n,F_{odd}(x^2)=a_1+a_3x^2+...+a_{n-1}x^{n-2}\)
\(F(x)=F_{even}(x^2) + xF_{odd}(x^2)\)!
\(F(-x)=F_{even}(x^2) - xF_{odd}(x^2)\)
我们不难发现现在我们的\(F(x)\)被拆成了一个偶函数\(F_{even}(x^2)\)和一个奇函数\(xF_{odd}(x^2)\)
现在我们对于取的点\((x_0,F(x_0))\)计算出\(F_{even}(x_0^2)\)和\(F_{odd}(x_0^2)\)后相加可得\(F(x)\),相减可得\(F(-x)\)
那我们怎么计算\(F_{even}(x_0^2)\)和\(F_{odd}(x_0^2)\)?
这不就是一个递归嘛,将\(x_0^2\)看作变量,继续来一遍拆分,直到我的函数只有常数项为止,由主定理可得时间复杂度为\(O(nlog_2n)\)
但是,我有\(x_0^2\)啊,原来的\(\pm x_0\)都会变成\(x_0^2\),我在递归去求子函数的值的时候取点全会变成正的,无法正负取点了,所以递归无法进行。
\(Chapter4:\) 数域推广
现在我们需要寻找一类数\(S\),满足\(\forall x \in S,-x \in S\)且对于由\(\forall x \in S, x^2\)构成的集合\(S'\)和\(S\)满足同样的性质
实数无法满足的原因是你无法在\(S'\)中找到\(-x\),因此我们将数域推广至复数
以前的注意力大神发现了单位根 就满足这样的性质
什么是单位根?
单位根\(\{\omega_n\}\)就是在复数域下所有满足 \(x^n=1\)的\(x\)构成的集合
我们不难发现\(\{\omega_n\}\)将复平面上的单位圆进行了\(n\)等分,所以我们可以得到单位根的表达式:
\(\omega^k_n = cos\theta+isin\theta,\theta=\frac{2\pi k}{n}\)
我们这个时候取点取\(\{\omega_n\}\)就可以满足条件了
\(Chapter5:\) FFT完全版
- 对于n项多项式\(F(x)\)取\(n\)次单位根为点
- 分奇偶函数递归计算\(F(\omega_n^i)\)
- 同样计算\(G(x)\)
- 将\(G(x)\)与\(F(x)\)以点坐标形式相乘
这就是FFT,很简单吧
但是我们发现这离结果还远着呢,所以我们需要从点表示转换为系数表示,因此我们需要插值操作
\(Chapter6:\) 插值
我们将待定系数列的方程组写为矩阵形式(\(P(x)\)系数为\(\{a_n\}\))
\( {\begin{bmatrix} P(\omega^0) \\\\ P(\omega^1) \\\\ P(\omega^2) \\\\ \vdots \\\\ P(\omega^{n-1}) \\\\ \end{bmatrix}} = {\begin{bmatrix} 1 & 1 & 1 & ... &1\\\\ 1 & \omega & \omega^2 & ... & \omega^{n-1}\\\\ 1&\omega^2&\omega^4&...&\omega^{2 (n-1)}\\\\ \vdots&\vdots&\vdots&\ddots&\vdots\\\\ 1&\omega^{n-1}&\omega^{2(n-1)}&...&\omega^{(n-1)(n-1)} \end{bmatrix}} {\begin{bmatrix} a_0 \\\\ a_1\\\\ a_2 \\\\ \vdots \\\\ a_{n-1} \\\\ \end{bmatrix}} \)
移项将\(\{a_n\}\)解出
\( {\begin{bmatrix} a_0 \\\\ a_1\\\\ a_2 \\\\ \vdots \\\\ a_{n-1} \end{bmatrix}} = {\begin{bmatrix} 1 & 1 & 1 & ... &1\\\\ 1 & \omega & \omega^2 & ... & \omega^{n-1}\\\\ 1&\omega^2&\omega^4&...&\omega^{2 (n-1)}\\\\ \vdots&\vdots&\vdots&\ddots&\vdots\\\\ 1&\omega^{n-1}&\omega^{2(n-1)}&...&\omega^{(n-1)(n-1)} \end{bmatrix}}^{-1} {\begin{bmatrix} P(\omega^0) \\\\ P(\omega^1) \\\\ P(\omega^2) \\\\ \vdots \\\\ P(\omega^{n-1}) \end{bmatrix}} \)
我们发现中间的那个矩阵为DFT(离散傅里叶变换)矩阵,因此可得
\( {\begin{bmatrix} a_0 \\\\ a_1\\\\ a_2 \\\\ \vdots \\\\ a_{n-1} \end{bmatrix}} = \frac{1}{n}{\begin{bmatrix} 1 & 1 & 1 & ... &1\\\\ 1 & \omega^{-1} & \omega^{-2} & ... & \omega^{-(n-1)}\\\\ 1&\omega^{-2}&\omega^{-4}&...&\omega^{-2 (n-1)}\\\\ \vdots&\vdots&\vdots&\ddots&\vdots\\\\ 1&\omega^{-(n-1)}&\omega^{-2(n-1)}&...&\omega^{-(n-1)(n-1)} \end{bmatrix}} {\begin{bmatrix} P(\omega^0) \\\\ P(\omega^1) \\\\ P(\omega^2) \\\\ \vdots \\\\ P(\omega^{n-1}) \end{bmatrix}} \)