整理的算法模板合集: ACM模板
目录
学习笔记(用ipad记录的笔记)
超级简单的快速傅里叶变换!只要基础够扎实,顺着推一遍没有什么难以理解的,我学的整个过程没有一点卡壳,真的很爽,整整写了三个多小时,写了满满6页的笔记。主要是内容太多了。又花了几个小时的时间整理整个过程,梳理出这篇博客,一万字有余。
我的数学博客一般都会包含全套证明,没有证明我会很难受的hhh。
一、概念概述
快速傅里叶变换 (fast Fourier transform), 即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。
离散傅里叶变换(Discrete Fourier Transform,缩写为 DFT),是傅里叶变换在时域和频域上都呈离散的形式,将信号的时域采样变换为其 DTFT 的频域采样。
FFT 是一种高效实现 DFT 的算法,称为快速傅立叶变换(Fast Fourier Transform,FFT)。它对傅里叶变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。快速数论变换 (NTT) 是快速傅里叶变换(FFT)在数论基础上的实现。
在 1965 年,Cooley 和 Tukey 发表了快速傅里叶变换算法。事实上 FFT 早在这之前就被发现过了,但是在当时现代计算机并未问世,人们没有意识到 FFT 的重要性。一些调查者认为 FFT 是由 Runge 和 König 在 1924 年发现的。但事实上高斯早在 1805 年就发明了这个算法,但一直没有发表。
上述内容摘自百度hhh
就是想让大家了解一下我们将要学的东西到底有多🐂🍺(●’◡’●)。然后进入我们今天的正题:
二、前置知识
首先是一些基础概念:
1. 多项式
多项式乘法 —— 卷积
我们上面说了多项式 × \times × 多项式 = = = 新的多项式。
所以我们最关心的操作就是两个多项式的乘法 —— 卷积。
广义上的卷积为:
h ( x ) = ∫ − ∞ ∞ g ( τ ) ⋅ f ( x − τ ) d τ {h(x) = \int _{- \infty} ^{\infty}g(\tau) \cdot f(x - \tau)} \rm{d\tau} h(x)=∫−∞∞g(τ)⋅f(x−τ)dτ
我们这里仅讨论多项式域,即两个多项式 / 数组 / 序列的卷积。
即给定两个多项式 f ( x ) f(x) f(x), g ( x ) g(x) g(x) :
f ( x ) = a 0 + a 1 x + ⋯ + a n x n f(x)= a_0 + a_1x+ \dots +a_nx^n f(x)=a0+a1x+⋯+anxn
g ( x ) = b 0 + b 1 x + ⋯ + b m x m g(x)= b_0 + b_1x+ \dots +b_mx^m g(x)=b0+b1x+⋯+bmxm
计算多项式 Q ( x ) = f ( x ) ⋅ g ( x ) : Q(x) = f(x)\ ·\ g(x): Q(x)=f(x) ⋅ g(x):
Q ( x ) = ∑ i = 0 n ∑ j = 0 m a i b j x i + j = c 0 + c 1 x + ⋯ + c n + m x n + m \boxed {Q(x) = \sum \limits_ {i = 0} ^ n \sum \limits_ {j = 0 } ^ m a_i b_j x ^ {i + j}} = c_0 + c_1 x + \dots + c_ {n + m} x ^ {n + m} Q(x)=i=0∑nj=0∑maibjxi+j=c0+c1x+⋯+cn+mxn+m
C ( x ) = A ( x ) ∗ B ( x ) = ∑ i = 0 n ( ∑ j = 0 i a j b i − j ) x j + i − j = ∑ i = 0 n ( ∑ j = 0 i a j b i − j ) x i C(x)=A(x)*B(x)=\sum_{i = 0}^{n}(\sum_{j=0}^{i}a_j b_{i-j})x^{j+i-j}=\sum_{i = 0}^{n}(\sum_{j=0}^{i}a_j b_{i-j})x^{i} C(x)=A(x)∗B(x)=i=0∑n(j=0∑iajbi−j)xj+i−j=i=0∑n(j=0∑iajbi−j)xi
也就是对于 C ( x ) C(x) C(x) 的第 i i i 项的系数:
[ i ] C ( x ) = ∑ j = 0 i a j b i − j [i]C(x)=\sum_{j=0}^{i}a_j b_{i-j} [i]C(x)=j=0∑iajbi−j
这里使用的就是上面介绍的系数表示,我们如果直接暴力相乘很明显是一个 O ( n m ) O(nm) O(nm) 的复杂度,因为我们每一项都需要相乘。但是我们可以通过快速傅里叶变换将常用的系数表示转为点值表示用 O ( n l o g n ) O(nlogn) O(nlogn) 的时间复杂度下计算得到答案,再逆变换转成系数表示输出
2. 复数
复数分为实部和虚部,可以描述为一个二元组 ( x , y ) (x,y) (x,y),表示这个数等于 x + y − 1 x+y\sqrt {-1} x+y−1。一般用 i i i 表示 − 1 \sqrt{-1} −1。
由于是个二元组,所以它在理解的时候可以抽象为一个二维向量,分布在平面直角坐标系上。
事实上,它确实也有不少性质和向量相同。
- 复数的模
定义复数的模,为复平面原点到 ( a , b ) (a,b) (a,b)的距离,即 ∣ z ∣ = x 2 + y 2 |z|=\sqrt {x^2+y^2} ∣z∣=x2+y2
定义 z z z 的范数 N ( z ) = ∣ z ∣ 2 = x 2 + y 2 N(z)=|z|^2=x^2+y^2 N(z)=∣z∣2=x2+y2。
- 共轭复数
复数 z = a + b i z=a+bi z=a+bi 的共轭是 z ′ = a − b i z'=a-bi z′=a−bi,记作 z ˉ \bar z zˉ。
性质: z × z ˉ = a 2 + b 2 z\times \bar z=a^2+b^2 z×zˉ=a2+b