[FFT] 快速傅里叶变换学习笔记

十分简明易懂的FFT(快速傅里叶变换) FFT有什么用 快速傅里叶变换 (fast Fourier transform),即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。 FFT(Fast Fouri... 阅读详情

-1、为什么学 FFT

退役(很早)之前听说 FFT 很神(e)奇(xin),Po姐来讲的时候也是膜(sha)了(ye)一(bu)发(dong),于是就放那里了。退役之后有(xian)了(de)时(mei)间(shi),并且在篮球赛之前立了赢一场的 flag 否则学FFT结果又双叒叕全输了,于是下面就是成果了……网上 FFT 讲解多得是不看也罢……

0、什么是 FFT?为什么 FFT?

0.1、为什么 FFT?

从一个简单问题说起:大整数乘法。在做 VijosP2000 的时候,看数据范围 O ( n 2 ) O(n^2) O(n2) 有点卡常?在做 HDOJ1402 的时候 O ( n 2 ) O(n^2) O(n2) 接着卡常?大整数乘法的时间复杂度只能是 O ( n 2 ) O(n^2) O(n2) 了?不是的。从算法优化上可以实现为 O ( n log ⁡ 2 3 ) O(n^{\log_2 3}) O(nlog2​3)的方法( log ⁡ 2 3 ≈ 1.585 \log_2 3\approx1.585 log2​3≈1.585,此方法为 Karatsuba 乘法,详解看这里),还是不太友好。那么就会用到 O ( n log ⁡ 2 n ) O(n\log_2 n) O(nlog2​n) 的 FFT 了。

0.2、什么是 FFT?

FFT(Fast Fourier Transform),全名快速傅里叶变换,这与傅里叶变换只有半毛钱的关系,傅里叶变换是分析波的成分的方法,通过推广傅里叶变换得到了优化的快速傅里叶变换,为了展示区别和联系,下面是傅里叶变换和傅里叶逆变换的公式:
傅里叶变换:
F ( ω ) = F [ f ( t ) ] = ∫ − ∞ ∞ f ( t ) e − i ω t d t F(\omega)=\mathcal{F}[f(t)]=\int\limits_{-\infty}^\infty f(t)e^{-i\omega t} dt F(ω)=F[f(t)]=−∞∫∞​f(t)e−iωtdt

傅里叶逆变换:

f ( t ) = F − 1 [ F ( ω ) ] = 1 2 π ∫ − ∞ ∞ F ( ω ) e i ω t d ω f(t)=\mathcal{F}^{-1}[F(\omega)]=\frac{1}{2\pi} \int\limits_{-\infty}^\infty F(\omega)e^{i\omega t} d\omega f(t)=F−1[F(ω)]=2π1​−∞∫∞​F(ω)eiωtdω

其中 f ( t ) f(t) f(t) 为以 t t t 为周期的周期函数, t t t 满足狄利赫里条件, F ( ω ) F(\omega) F(ω) 称为 f ( t ) f(t) f(t) 的像函数, f ( t ) f(t) f(t) 称为 F ( ω ) F(\omega) F(ω) 的原像函数。具体问题请参考《高等数学》,博主还是高中生……(高中高等数学233333)
然后,我们终于可以开始讲 FFT 了…

1 、(初中知识)多项式

1.1、定义

我们把形如 a 0 + a 1 x + a 2 x 2 + ⋯ + a n − 1 x n − 1 a_0+a_1x+a_2x^2+\cdots+a_{n-1}x^{n-1} a0​+a1​x+a2​x2+⋯+an−1​xn−1 的式子叫做多项式,其中 a 0 , a 1 , ⋯   , a n − 1 a_0,a_1,\cdots,a_{n-1} a0​,a1​,⋯,an−1​ 称为多项式的系数,多项式中单项式个数为多项式的项数。因为多项式由单项式组成,规定最高次项的次数叫做多项式的次数,这里 A ( x ) A(x) A(x) 的次数为 n − 1 n-1 n−1。 x x x 为未知数。
以上内容均为初二(我记得是)的内容,不明白的自觉面壁思过(初中数学老师:这个定义抄 10 10 10 遍给我)……
下面就是没学过的了:
为方便表示,我们记多项式 a 0 + a 1 x + a 2 x 2 + ⋯ + a n − 1 x n − 1 a_0+a_1x+a_2x^2+\cdots+a_{n-1}x^{n-1} a0​+a1​x+a2​x2+⋯+an−1​xn−1 为 A ( x ) A(x) A(x),即:

A ( x ) = ∑ i = 0 n − 1 a i x i A(x)=\sum\limits_{i=0}^{n-1}a_ix^i A(x)=i=0∑n−1​ai​xi

我们规定:严格大于 n n n 的任意整数为这个多项式的次数界,即次数的范围。多项式中任意单项式次数均严格小于次数界。
哦,行……
下面无特殊说明,多项式均用 A ( x ) A(x) A(x) 等类似形式表示。

1.2、多项式的两种表示法

1.2.1、系数表示法

我们知道,向量是个好东西(蛤?),矩阵也是个好东西(蛤?),于是我们把三者结合起来看(蛤玩意?)。
我们将 n − 1 n-1 n−1 次多项式的系数看成 n n n 维向量,即 a ⃗ = ( a 0 , a 1 , ⋯   , a n − 1 ) \vec a=(a_0,a_1,\cdots,a_{n-1}) a =(a0​,a1​,⋯,an−1​),则称 a ⃗ \vec a a 为多项式 A ( x ) A(x) A(x) 的系数表示。
在选修 4-2 中,我们知道向量与矩阵有着密切联系,这就是为什么我们把多项式,向量和矩阵联系起来。(然而我们并没选 4-2 蛤蛤蛤)
于是这个 n n n 维向量可以表示为一个 n n n 维列向量,为:
[ a 0 a 1 ⋮ a n − 1 ] \begin{bmatrix} a_0\\ a_1\\ \vdots \\ a_{n-1} \end{bmatrix} ⎣⎢⎢⎢⎡​a0​a1​⋮an−1​​⎦⎥⎥⎥⎤​

1.2.2、点值表示法

我们把多项式 A ( x ) A(x) A(x) 看做一个函数,选取不同的 n n n 个值 x 0 , x 1 , ⋯   , x n − 1 x_0,x_1,\cdots,x_{n-1} x0​,x1​,⋯,xn−1​ 代入 A ( x ) A(x) A(x) 中,可以得到 A ( x ) A(x) A(x) 的图像上 n n n 个不同的点,那么称点集 α = { ( x i , A ( x i ) ) ∣ i ∈ [ 0 , n − 1 ] , i ∈ Z } \alpha=\{ (x_i,A(x_i))\mid i\in[0,n-1],i\in \mathbb{Z}\} α={(xi​,A(xi​))∣i∈[0,n−1],i∈Z} 为多项式 A ( x ) A(x) A(x) 的点值表示。
到这里,是不是差不多忘了要干什么了……

1.3、多项式的运算

1.3.1、多项式求值

这个比较简单,拿题说。这是我还没出也不想出的一道题,拿出来娱乐一下……
题目描述 Description

都知道 FZ 酱数学不好,数学老师很着急,于是让她求个多项式的值。但是数学老师一不小心数据就出大了,他却并没有注意到这一点。老师共出了 T T T 道题,FZ 酱拿到了这 T T T 道题就崩溃了,请帮她尽快完成作业。

输入 Input

第一行一个整数 T T T,表示数据组数。
对于每组数据:
第一行有一个数 n n n 表示这个多项式的次数界;
第二行有 n n n 个整数 a 0 , a 1 , ⋯   , a n − 1 a_0,a_1,\cdots\ ,a_{n-1} a0​,a1​,⋯ ,an−1​,表示多项式 ∑ i = 0 n − 1 a i x i \sum\limits_{i=0}^{n-1}a_ix^i i=0∑n−1​ai​xi;
第三行,为未知数的值 x x x。

输出 Output

对于每组数据,输出一行,为答案。

样例输入 Sample Input

2
2
3 2
100
3
1 2 3
-9

样例输出 Sample Output

203
226

样例解释 Explanation

对于第一个多项式为 A ( x ) = 2 x + 3 A(x)=2x+3 A(x)=2x+3,代入后得 A ( 100 ) = 2 × 100 + 3 = 203 A(100)=2\times 100+3=203 A(100)=2×100+3=203;
对于第二个多项式为 A ( x ) = 3 x 2 + 2 x + 1 A(x)=3x^2+2x+1 A(x)=3x2+2x+1,代入后得 A ( − 9 ) = 226 A(-9)=226 A(−9)=226。

限制 Limits

对于 50 % 50\% 50% 的数据,答案在 [ 0 , 2 128 − 1 ] [0,2^{128}-1] [0,2128−1] 范围内;
对于 100 % 100\% 100% 的数据, T ≤ 2 T\le 2 T≤2, n ≤ 1 0 5 n\le 10^5 n≤105,保证输入均为绝对值不大于 2 31 − 1 2^{31}-1 231−1 的整数并且答案小于 3 × 1 0 6 3\times 10^6 3×106 位。

那么很好我们必须写高精度了……
2 128 − 1 ≈ 3.4 × 1 0 38 2^{128}-1\approx 3.4\times 10^{38} 2128−1≈3.4×1038,这里的 50 % 50\% 50% 数据是给不想写高精度的童鞋写 __int128 准备的(__int128 的范围是 [ 0 , 2 128 − 1 ] [0,2^{128}-1] [0,2128−1])。于是我们就有这样三种的方法。
记数字长度为 p p p。

1.3.1.1、方法一: O ( p n 2 ) → 50 pts O(pn^2)\to 50\text{pts} O(pn2)→50pts

暴力不会吗?
核心代码如下:
4

1.3.1.2、方法二: O ( p 2 n log ⁡ n ) → [ 50 , 80 ] pts O(p^2n\log n)\to [50,80]\text{pts} O(p2nlogn)→[50,80]pts

这里挨个乘太慢了,快速幂处理会快一些。
(其实不一定会快多少)
核心代码如下:
2

1.3.1.3、方法三: O ( p 2 n ) → 100 pts O(p^2n)\to 100\text{pts} O(p2n)→100pts

学过必修三吗?
学过必修三还不会?
拿出数学必修三翻到 37 页你看到了什么?
秦九韶算法可以大量减少乘法和加法次数,并且把运算量简化为 O ( n ) O(n) O(n) 的。
核心代码如下:
3
当然,还可以处理前缀积,也是 O ( n ) O(n) O(n) 的。
核心代码如下:
1
不过没上面的优雅不是吗……(呵呵)
回到正题上,我们要谈的其实是……

1.3.2、多项式的加法和乘法

1.3.2.1、多项式加法

没啥难度,直接加即可:
C ( x ) = A ( x ) + B ( x ) = ∑ i = 0 n − 1 a i x i + ∑ j = 0 n − 1 b j x j = ∑ i = 0 n − 1 ( a i + b i ) x i = ∑ i = 0 n − 1 c i x i \begin{aligned} C(x)&=A(x)+B(x)\\ &=\sum\limits_{i=0}^{n-1}a_ix^i+\sum\limits_{j=0}^{n-1}b_jx^j\\ &=\sum\limits_{i=0}^{n-1}(a_i+b_i)x^i\\ &=\sum\limits_{i=0}^{n-1}c_ix^i \end{aligned} C(x)​=A(x)+B(x)=i=0∑n−1​ai​xi+j=0∑n−1​bj​xj=i=0∑n−1​(ai​+bi​)xi=i=0∑n−1​ci​xi​
这个操作可以 O ( n ) O(n) O(n) 完成。

1.3.2.2、多项式乘法

这就是个开括号的问题……
两个次数界为 n a , n b n_a,n_b na​,nb​ 的多项式 A ( x ) , B ( x ) A(x),B(x) A(x),B(x) 相乘,得到的多项式 C ( x ) C(x) C(x) 的次数界为 n a + n b − 1 n_a+n_b-1 na​+nb​−1。
我们把不足的次数用系数 0 0 0 补充,变成两个齐次多项式。
考虑怎样的两项乘完后,结果的幂指数为同一个。即 a i x i × b j x j = c k x k a_ix^i\times b_jx^j=c_kx^k ai​xi×bj​xj=ck​xk, i , j i,j i,j 怎样取值才能使 k k k 为定值。显然 k = i + j k=i+j k=i+j。
那么乘完之后, C ( x ) C(x) C(x) 就可以知道了。
C ( x ) = ∑ i = 0 2 n − 2 ( ∑ j = 0 i a j b i − j ) x i = ∑ i = 0 2 n − 2 c i x i \begin{aligned} C(x)&=\sum\limits_{i=0}^{2n-2}(\sum\limits_{j=0}^ia_jb_{i-j})x^i\\ &=\sum\limits_{i=0}^{2n-2}c_ix^i \end{aligned} C(x)​=i=0∑2n−2​(j=0∑i​aj​bi−j​)xi=i=0∑2n−2​ci​xi​
我们把中间的那个加法,即 c i = ∑ j = 0 i a j b i − j c_i=\sum\limits_{j=0}^ia_jb_{i-j} ci​=j=0∑i​aj​bi−j​ 叫做卷积。
这样,朴素算法时间复杂度为 O ( n 2 ) O(n^2) O(n2),显然不是太好。
但是点值表达式的表示就很好了,直接乘起来就好了嘛!即:
设 A ( x ) A(x) A(x) 的点值表示为 α = { ( x i , A ( x i ) ) ∣ i ∈ [ 0 , n − 1 ] , i ∈ Z } \alpha=\{ (x_i,A(x_i))\mid i\in[0,n-1],i\in \mathbb{Z}\} α={(xi​,A(xi​))∣i∈[0,n−1],i∈Z},设 B ( x ) B(x) B(x) 的点值表示为 β = { ( x i , B ( x i ) ) ∣ i ∈ [ 0 , n − 1 ] , i ∈ Z } \beta=\{ (x_i,B(x_i))\mid i\in[0,n-1],i\in \mathbb{Z}\} β={(xi​,B(xi​))∣i∈[0,n−1],i∈Z},然后就能得到 C ( x ) C(x) C(x) 的点值表示为: γ = { ( x i , A ( x i ) B ( x i ) ) ∣ i ∈ [ 0 , n − 1 ] , i ∈ Z } \gamma=\{ (x_i,A(x_i)B(x_i))\mid i\in[0,n-1],i\in \mathbb{Z}\} γ={(xi​,A(xi​)B(xi​))∣i∈[0,n−1],i∈Z},但是这里只是两多项式的积。并不是真正的点值表示,不过也够用了。

1.4、插值-点值转换

就要接近重点了同志们加油!
先定义两个运算:
1、定义一种运算,可以将系数表示转化为点值表示,记为 DFT ( A ( x ) ) = α \text{DFT}(A(x))=\alpha DFT(A(x))=α;
2、定义其逆运算,即从一个多项式的点值表示确定其系数表示为插值。记为 DFT − 1 ( α ) = IDFT ( α ) = A ( x ) \text{DFT}^{-1}(\alpha)=\text{IDFT}(\alpha)=A(x) DFT−1(α)=IDFT(α)=A(x)。
第一个运算在 x i x_i xi​ 确定时唯一确定,那么第二个在 x i x_i xi​ 确定时可不可以唯一确定 A ( x ) A(x) A(x) 呢?
答案是肯定的。我们把这些点代入,可以得出一个 n n n 元一次方程组,当 x i x_i xi​ 均不相同时,可以唯一确定 a 0 , a 1 , ⋯   , a n a_0,a_1,\cdots ,a_n a0​,a1​,⋯,an​。(如果有一个 x i x_i xi​ 相同立刻变成不定方程)
当然可以拿矩阵证明网上多得是。
那么就很尴尬, DFT ( A ( x ) ) \text{DFT}(A(x)) DFT(A(x)) 的复杂度是 O ( n 2 ) O(n^2) O(n2) 的,它的逆运算是 O ( n 3 ) O(n^3) O(n3) 的(高斯消元)……还不如不优化了。
所以我们还需要一些姿势。

2、(高中知识)复数

一些奇奇怪怪的问题无法解决,可以把它从实数域扩展到复数域上解决,加入了复数这种类似向量的东西,问题就会变得简单。
噫,向量?点值表示不就是个向量吗!

2.1、定义

一堆定义就不说了,选修 2-2 内容,这里简单的强调一些运算:
i 2 = − 1 i^2=-1 i2=−1
设 z 1 , z 2 ∈ C z_1,z_2\in \mathbb{C} z1​,z2​∈C, z 1 = a + b i , z 2 = c + d i z_1=a+bi,z_2=c+di z1​=a+bi,z2​=c+di,则:
z 1 ± z 2 = ( a ± c ) + ( b ± d ) i z_1\pm z_2=(a\pm c)+(b\pm d)i z1​±z2​=(a±c)+(b±d)i
z 1 × z 2 = ( a c − b d ) + ( a d + b c ) i z_1\times z_2=(ac-bd)+(ad+bc)i z1​×z2​=(ac−bd)+(ad+bc)i
z 1 z 2 = a c + b d c 2 + d 2 + b c − a d c 2 + d 2 i \frac{z_1}{z_2}=\frac{ac+bd}{c^2+d^2}+\frac{bc-ad}{c^2+d^2}i z2​z1​​=c2+d2ac+bd​+c2+d2bc−ad​i
设 z ∈ C z\in \mathbb{C} z∈C, z = a + b i z=a+bi z=a+bi,则 z z z 的共轭复数为 z ‾ = a − b i \overline z=a-bi z=a−bi
这是学过的,下面就说说没学过的。

2.2、单位根

根?方程的根?什么方程的根?
定义: x n = 1 x^n=1 xn=1 的所有根叫做 n n n 次单位根。
当我们把问题引入复数域, x x x 就不能简单计算为 x = 1 n = 1 x=\sqrt[n] 1=1 x=n1 ​=1了,而是在复平面内解决问题。

2.3、欧拉公式

一个很 6 的公式。内容是:
e i x = cos ⁡ x + i sin ⁡ x e^{ix}=\cos x+i\sin x eix=cosx+isinx
式子很简单,证明如下:
由 Taylor 展开:
e x = 1 + x + x 2 2 ! + ⋯ + x n n ! + ⋯ cos ⁡ x = 1 − x 2 2 ! + x 4 4 ! − x 6 6 ! + ⋯ sin ⁡ x = x − x 3 3 ! + x 5 5 ! − x 7 7 ! + ⋯ \begin{aligned} e^x&=1+x+\frac{x^2}{2!}+\cdots +\frac{x^n}{n!}+\cdots \\ \cos x&=1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\cdots \\ \sin x&=x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\cdots \\ \end{aligned} excosxsinx​=1+x+2!x2​+⋯+n!xn​+⋯=1−2!x2​+4!x4​−6!x6​+⋯=x−3!x3​+5!x5​−7!x7​+⋯​
将 Taylor 展开推广到复数域上,有复数运算 ± i = ± i , ( ± i ) 2 = − 1 , ( ± i ) 3 = ∓ i , ( ± i ) 4 = 1 \pm i=\pm i,(\pm i)^2=-1,(\pm i)^3=\mp i,(\pm i)^4=1 ±i=±i,(±i)2=−1,(±i)3=∓i,(±i)4=1,可得:
e i x = 1 + i x − x 2 2 ! − i x 3 3 ! + x 4 4 ! + i x 5 5 ! + ⋯ = ( 1 − x 2 2 ! + x 4 4 ! − ⋯   ) + i ( x − x 3 3 ! + x 5 5 ! − ⋯   ) = cos ⁡ x + i sin ⁡ x \begin{aligned} e^{ix}&=1+ix-\frac{x^2}{2!}-i\frac{x^3}{3!}+\frac{x^4}{4!}+i\frac{x^5}{5!}+\cdots \\ &=(1-\frac{x^2}{2!}+\frac{x^4}{4!}-\cdots)+i(x-\frac{x^3}{3!}+\frac{x^5}{5!}-\cdots)\\ &=\cos x+i\sin x \end{aligned} eix​=1+ix−2!x2​−i3!x3​+4!x4​+i5!x5​+⋯=(1−2!x2​+4!x4​−⋯)+i(x−3!x3​+5!x5​−⋯)=cosx+isinx​
证毕。
将 x x x 换成 π \pi π,就出现了 e π i = − 1 e^{\pi i}=-1 eπi=−1,即 e π i + 1 = 0 e^{\pi i}+1=0 eπi+1=0,被誉为上帝创造的公式。
将 x x x 换成 2 k π    ( k ∈ Z ) 2k\pi\ \ (k\in \mathbb{Z}) 2kπ  (k∈Z),就出现了 e 2 k π i = 1 e^{2k\pi i}=1 e2kπi=1。
我们不是要解 x n = 1 x^n=1 xn=1 吗!
那么 x = e 2 k π i n    ( k ∈ Z ) x=e^{\frac{2k\pi i}{n}} \ \ (k \in \mathbb{Z}) x=en2kπi​  (k∈Z),记这些单位根为 ω n k = e 2 k π i n \omega _n^k=e^{\frac{2k\pi i}{n}} ωnk​=en2kπi​。
下面就是一些数论问题了……
记 k = n r + p k=nr+p k=nr+p,其中 p ∈ [ 0 , n − 1 ] p\in[0,n-1] p∈[0,n−1],则 ω n k = e 2 p π i n \omega _n^k=e^{\frac{2p\pi i}{n}} ωnk​=en2pπi​
ω n k = e 2 k π i n = e 2 ( n r + p ) π i n = e 2 n r π i n + 2 p π i n = e 2 n r π i n × e 2 p π i n = e 2 π i r × e 2 p π i n = 1 r × e 2 p π i n = e 2 p π i n \begin{aligned} \omega _n^k&=e^{\frac{2k\pi i}{n}}\\ &=e^{\frac{2(nr+p)\pi i}{n}}\\ &=e^{\frac{2nr\pi i}{n}+\frac{2p\pi i}{n}}\\ &=e^{\frac{2nr\pi i}{n}}\times e^{\frac{2p\pi i}{n}}\\ &=e^{2\pi ir}\times e^{\frac{2p\pi i}{n}}\\ &=1^r\times e^{\frac{2p\pi i}{n}}=e^{\frac{2p\pi i}{n}} \end{aligned} ωnk​​=en2kπi​=en2(nr+p)πi​=en2nrπi​+n2pπi​=en2nrπi​×en2pπi​=e2πir×en2pπi​=1r×en2pπi​=en2pπi​​
这不一样吗……
所以可以证明 k ∈ [ 0 , n − 1 ] k\in [0,n-1] k∈[0,n−1]。也就是 n n n 次单位根有 n n n 个,不难发现,这 n n n 个单位根就是单位圆上的 n n n 个 n n n 等分点。
于是记这些根为 ω n 0 , ω n 1 , ⋯   , ω n n − 1 \omega_n^0,\omega_n^1,\cdots ,\omega_n^{n-1} ωn0​,ωn1​,⋯,ωnn−1​,这些根各不相同,并且在乘法意义下构成一个群。即: ω n i ω n j = ω n i + j = ω n ( i + j )   m o d   n \omega_n^i\omega_n^j=\omega_n^{i+j}=\omega_n^{(i+j)\bmod n} ωni​ωnj​=ωni+j​=ωn(i+j)modn​,且 ω n − 1 = ω n n − 1 \omega_n^{-1}=\omega_n^{n-1} ωn−1​=ωnn−1​,证明如下:
ω n − 1 = 1 × ω n − 1 = e 2 π i × e − 2 π i n = e 2 π i − − 2 π i n = e 2 ( n − 1 ) π i n = ω n n − 1 \begin{aligned} \omega_n^{-1}&=1\times \omega_n^{-1}\\ &=e^{2\pi i}\times e^{\frac{-2\pi i}{n}}\\ &=e^{2\pi i-\frac{-2\pi i}{n}}\\ &=e^{\frac{2(n-1)\pi i}{n}}=\omega_n^{n-1} \end{aligned} ωn−1​​=1×ωn−1​=e2πi×en−2πi​=e2πi−n−2πi​=en2(n−1)πi​=ωnn−1​​
问题得证。

2.4、三个引理

2.4.1、消去引理

内容:当 d ≠ 0 d\not =0 d​=0 时, ω d n d k = ω n k \omega_{dn}^{dk}=\omega_n^k ωdndk​=ωnk​。
证明:
ω d n d k = e 2 d k π i d n = e 2 k π i n = ω n k \begin{aligned} \omega_{dn}^{dk}&=e^{\frac{2dk\pi i}{dn}}\\ &=e^{\frac{2k\pi i}{n}}=\omega_n^k \end{aligned} ωdndk​​=edn2dkπi​=en2kπi​=ωnk​​
很简单……也很智障

2.4.2、折半引理

内容:如果 n > 0 n>0 n>0 且 n n n 为偶数, ( ω n k ) 2 = ω n 2 k (\omega_n^k)^2=\omega_{\frac{n}{2}}^k (ωnk​)2=ω2n​k​。
证明:
( ω n k ) 2 = ( e 2 k π i n ) 2 = e 2 k π i n 2 = ω n 2 k \begin{aligned} (\omega_{n}^{k})^2&=(e^{\frac{2k\pi i}{n}})^2\\ &=e^{\frac{2k\pi i}{\frac{n}{2}}}=\omega_{\frac{n}{2}}^k \end{aligned} (ωnk​)2​=(en2kπi​)2=e2n​2kπi​=ω2n​k​​
还行吧……可以看出, n n n 个 n n n 次单位根平方的集合就是 n 2 \frac{n}{2} 2n​ 个 n 2 \frac{n}{2} 2n​ 次单位根的集合,并且每个元素出现两次。可以通过单位根的对称性来理解。
更一般的结论:
ω n k + n 2 = ω n n 2 ω n k = − ω n k \omega_n^{k+\frac{n}{2}}=\omega_n^{\frac{n}{2}}\omega_n^k=-\omega_n^k ωnk+2n​​=ωn2n​​ωnk​=−ωnk​
ω n n 2 = e π i = − 1 \omega_n^{\frac{n}{2}}=e^{\pi i}=-1 ωn2n​​=eπi=−1

2.4.3、求和引理

内容:对于 ∀ k ∈ ( 0 , n ) \forall k\in(0,n) ∀k∈(0,n),有 ∑ j = 0 n − 1 ( ω n k ) j = 0 \sum\limits_{j=0}^{n-1}(\omega_n^k)^j=0 j=0∑n−1​(ωnk​)j=0。
证明:
∑ j = 0 n − 1 ( ω n k ) j = 1 − ( ω n k ) n 1 − ω n k ( 等 比 数 列 求 和 ) = 1 − ( ω n n ) k 1 − ω n k = 0 \begin{aligned} \sum\limits_{j=0}^{n-1}(\omega_n^k)^j &=\frac{1-(\omega_{n}^{k})^n}{1-\omega_{n}^{k}}(等比数列求和)\\ &=\frac{1-(\omega_{n}^{n})^k}{1-\omega_{n}^{k}}=0 \end{aligned} j=0∑n−1​(ωnk​)j​=1−ωnk​1−(ωnk​)n​(等比数列求和)=1−ωnk​1−(ωnn​)k​=0​
注意: ω n n = 1 \omega_n^n=1 ωnn​=1,化简省略了部分很多步骤。
现在全都就绪了,终于要到目标了……

3、离散傅里叶变换(DFT)

DFT,即 Discrete Fourier Transform,离散傅里叶变换,就是我们之前定义的那个,现在有了复数,我们就可以在 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的时间内做完 DFT 运算。运用到了 Cooley-Tukey 算法。
我们将多项式按照指数的奇偶分类,记原多项式为 A ( x ) A(x) A(x),那么构造两个多项式:
A 0 ( x ) = a 0 + a 2 x + a 4 x 2 + ⋯ + a n − 2 x n 2 − 1 = ∑ i = 0 n 2 − 1 a 2 i x i A 1 ( x ) = a 1 + a 3 x + a 5 x 2 + ⋯ + a n − 1 x n 2 − 1 = ∑ i = 0 n 2 − 1 a 2 i + 1 x i \begin{aligned} A_0(x)&=a_0+a_2x+a_4x^2+\cdots +a_{n-2}x^{\frac{n}{2}-1}\\ &=\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i}x^i\\ A_1(x)&=a_1+a_3x+a_5x^2+\cdots +a_{n-1}x^{\frac{n}{2}-1}\\ &=\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i+1}x^i\\ \end{aligned} A0​(x)A1​(x)​=a0​+a2​x+a4​x2+⋯+an−2​x2n​−1=i=0∑2n​−1​a2i​xi=a1​+a3​x+a5​x2+⋯+an−1​x2n​−1=i=0∑2n​−1​a2i+1​xi​
通过观察可知, A ( x ) = A 0 ( x 2 ) + x A 1 ( x 2 ) A(x)=A_0(x^2)+xA_1(x^2) A(x)=A0​(x2)+xA1​(x2),根据折半引理,我们考虑将 n n n 次单位根作为 x x x 代入计算。又因为折半引理,我们即可分治操作。
那么,对于 k < n 2 k<\frac{n}{2} k<2n​,有:
A ( ω n k ) = A 0 ( ( ω n k ) 2 ) + ω n k A 1 ( ( ω n k ) 2 ) = A 0 ( ω n 2 k ) + ω n k A 1 ( ω n 2 k ) = ∑ i = 0 n 2 − 1 a 2 i ω n 2 k i + ω n k ∑ i = 0 n 2 − 1 a 2 i + 1 ω n 2 k i A ( ω n k + n 2 ) = A 0 ( ( ω n k ) 2 ) + ω n k + n 2 A 1 ( ( ω n k ) 2 ) = A 0 ( ω n 2 k ) − ω n k A 1 ( ω n 2 k ) = ∑ i = 0 n 2 − 1 a 2 i ω n 2 k i − ω n k ∑ i = 0 n 2 − 1 a 2 i + 1 ω n 2 k i \begin{aligned} A(\omega_n^k)&=A_0((\omega_n^k)^2)+\omega_n^kA_1((\omega_n^k)^2)\\ &=A_0(\omega_{\frac{n}{2}}^k)+\omega_n^kA_1(\omega_{\frac{n}{2}}^k)\\ &=\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i}\omega_{\frac{n}{2}}^{ki}+\omega_n^k\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i+1}\omega_{\frac{n}{2}}^{ki}\\ A(\omega_n^{k+\frac{n}{2}})&=A_0((\omega_n^k)^2)+\omega_n^{k+\frac{n}{2}}A_1((\omega_n^k)^2)\\ &=A_0(\omega_{\frac{n}{2}}^k)-\omega_n^kA_1(\omega_{\frac{n}{2}}^k)\\ &=\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i}\omega_{\frac{n}{2}}^{ki}-\omega_n^k\sum\limits_{i=0}^{\frac{n}{2}-1}a_{2i+1}\omega_{\frac{n}{2}}^{ki} \end{aligned} A(ωnk​)A(ωnk+2n​​)​=A0​((ωnk​)2)+ωnk​A1​((ωnk​)2)=A0​(ω2n​k​)+ωnk​A1​(ω2n​k​)=i=0∑2n​−1​a2i​ω2n​ki​+ωnk​i=0∑2n​−1​a2i+1​ω2n​ki​=A0​((ωnk​)2)+ωnk+2n​​A1​((ωnk​)2)=A0​(ω2n​k​)−ωnk​A1​(ω2n​k​)=i=0∑2n​−1​a2i​ω2n​ki​−ωnk​i=0∑2n​−1​a2i+1​ω2n​ki​​
这样,由奇偶性使得需要代入的值范围减半,递归做下去就行了,时间复杂度为:
T ( n ) = 2 T ( n 2 ) + O ( n ) = O ( n log ⁡ n ) T(n)=2T(\frac{n}{2})+O(n)=O(n\log n) T(n)=2T(2n​)+O(n)=O(nlogn)
因为永远是奇偶合并,如果想要更方便地合并必然 n n n 取 2 2 2 的整数次幂,否则合并到一定时候左右不一定都是相同次数(可以考虑一个完全二叉树)。所以做的时候取 2 2 2 的整数次幂作为 n n n。

4、逆离散傅里叶变换(IDFT)

IDFT,即 Inverse Discrete Fourier Transform,逆离散傅里叶变换,还是我们之前定义的那个。我们在 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的时间里搞定了 DFT,可是 IDFT 还是个 O ( n 3 ) O(n^3) O(n3)的,所以我们继续观(tui)察(da)性(shi)质(zi)。
我们说过,IDFT 相当于解个 n n n 元一次方程组,这个方程组写成矩阵形式是这样的:
[ ( ω n 0 ) 0 ( ω n 0 ) 1 ( ω n 0 ) 2 ⋯ ( ω n 0 ) n − 1 ( ω n 1 ) 0 ( ω n 1 ) 1 ( ω n 1 ) 2 ⋯ ( ω n 1 ) n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ ( ω n n − 1 ) 0 ( ω n n − 1 ) 1 ( ω n n − 1 ) 2 ⋯ ( ω n n − 1 ) n − 1 ] × [ a 0 a 1 ⋮ a n − 1 ] = [ A ( ω n 0 ) A ( ω n 1 ) A ( ω n 2 ) ⋮ A ( ω n n − 1 ) ] \begin{bmatrix} (\omega_n^0)^0& (\omega_n^0)^1&(\omega_n^0)^2 &\cdots &(\omega_n^0)^{n-1}\\ (\omega_n^1)^0& (\omega_n^1)^1&(\omega_n^1)^2&\cdots &(\omega_n^1)^{n-1}\\ \vdots&\vdots &\vdots &\ddots &\vdots \\ (\omega_n^{n-1})^0 & (\omega_n^{n-1})^1& (\omega_n^{n-1})^2&\cdots & (\omega_n^{n-1})^{n-1} \end{bmatrix} \times \begin{bmatrix} a_0\\a_1\\ \vdots \\a_{n-1} \end{bmatrix}= \begin{bmatrix} A(\omega_n^0)\\ A(\omega_n^1)\\ A(\omega_n^2)\\ \vdots \\ A(\omega_n^{n-1})\\ \end{bmatrix} ⎣⎢⎢⎢⎡​(ωn0​)0(ωn1​)0⋮(ωnn−1​)0​(ωn0​)1(ωn1​)1⋮(ωnn−1​)1​(ωn0​)2(ωn1​)2⋮(ωnn−1​)2​⋯⋯⋱⋯​(ωn0​)n−1(ωn1​)n−1⋮(ωnn−1​)n−1​⎦⎥⎥⎥⎤​×⎣⎢⎢⎢⎡​a0​a1​⋮an−1​​⎦⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎡​A(ωn0​)A(ωn1​)A(ωn2​)⋮A(ωnn−1​)​⎦⎥⎥⎥⎥⎥⎤​
这同时也是做 DFT 时我们乘的矩阵。只不过这次 a i a_i ai​ 变成未知数了。
记上面的系数矩阵为 D D D,再考虑以下矩阵:
[ ( ω n 0 ) 0 ( ω n 0 ) 1 ( ω n 0 ) 2 ⋯ ( ω n 0 ) n − 1 ( ω n − 1 ) 0 ( ω n − 1 ) 1 ( ω n − 1 ) 2 ⋯ ( ω n − 1 ) n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ ( ω n − ( n − 1 ) ) 0 ( ω n − ( n − 1 ) ) 1 ( ω n − ( n − 1 ) ) 2 ⋯ ( ω n − ( n − 1 ) ) n − 1 ] \begin{bmatrix} (\omega_n^0)^0& (\omega_n^0)^1&(\omega_n^0)^2 &\cdots &(\omega_n^0)^{n-1}\\ (\omega_n^{-1})^0& (\omega_n^{-1})^1&(\omega_n^{-1})^2&\cdots &(\omega_n^{-1})^{n-1}\\ \vdots&\vdots &\vdots &\ddots &\vdots \\ (\omega_n^{-(n-1)})^0 & (\omega_n^{-(n-1)})^1& (\omega_n^{-(n-1)})^2&\cdots & (\omega_n^{-(n-1)})^{n-1} \end{bmatrix} ⎣⎢⎢⎢⎡​(ωn0​)0(ωn−1​)0⋮(ωn−(n−1)​)0​(ωn0​)1(ωn−1​)1⋮(ωn−(n−1)​)1​(ωn0​)2(ωn−1​)2⋮(ωn−(n−1)​)2​⋯⋯⋱⋯​(ωn0​)n−1(ωn−1​)n−1⋮(ωn−(n−1)​)n−1​⎦⎥⎥⎥⎤​
记此矩阵为 W W W,则记 E = D × W E=D\times W E=D×W。可知:
E i j = ∑ k = 0 n − 1 D i k W k j = ∑ k = 0 n − 1 ω n − i k ω n k j = ∑ k = 0 n − 1 ω n k ( j − i ) \begin{aligned} E_{ij}&=\sum\limits_{k=0}^{n-1}D_{ik}W_{kj}\\ &=\sum\limits_{k=0}^{n-1}\omega_n^{-ik}\omega_n^{kj}\\ &=\sum\limits_{k=0}^{n-1}\omega_n^{k(j-i)} \end{aligned} Eij​​=k=0∑n−1​Dik​Wkj​=k=0∑n−1​ωn−ik​ωnkj​=k=0∑n−1​ωnk(j−i)​​
当 i = j i=j i=j 时:
E i j = ∑ k = 0 n − 1 ω n k ( j − i ) = ∑ k = 0 n − 1 ω n 0 = n \begin{aligned} E_{ij}&=\sum\limits_{k=0}^{n-1}\omega_n^{k(j-i)}\\ &=\sum\limits_{k=0}^{n-1}\omega_n^0=n\\ \end{aligned} Eij​​=k=0∑n−1​ωnk(j−i)​=k=0∑n−1​ωn0​=n​
当 i ≠ j i\not =j i​=j 时,由求和引理:
E i j = ∑ k = 0 n − 1 ω n k ( j − i ) = ∑ k = 0 n − 1 ( ω n j − i ) k = 0 \begin{aligned} E_{ij}&=\sum\limits_{k=0}^{n-1}\omega_n^{k(j-i)}\\ &=\sum\limits_{k=0}^{n-1}(\omega_n^{j-i})^k=0\\ \end{aligned} Eij​​=k=0∑n−1​ωnk(j−i)​=k=0∑n−1​(ωnj−i​)k=0​
记单位矩阵为 I I I,所以 I = 1 n E I=\frac{1}{n}E I=n1​E,即 1 n D = W − 1 \frac{1}{n}D=W^{-1} n1​D=W−1。
将由方程组推得那个矩阵左乘 1 n D \frac{1}{n}D n1​D,可得:
[ a 0 a 1 ⋮ a n − 1 ] = [ ( ω n 0 ) 0 ( ω n 0 ) 1 ( ω n 0 ) 2 ⋯ ( ω n 0 ) n − 1 ( ω n − 1 ) 0 ( ω n − 1 ) 1 ( ω n − 1 ) 2 ⋯ ( ω n − 1 ) n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ ( ω n − ( n − 1 ) ) 0 ( ω n − ( n − 1 ) ) 1 ( ω n − ( n − 1 ) ) 2 ⋯ ( ω n − ( n − 1 ) ) n − 1 ] × [ A ( ω n 0 ) A ( ω n 1 ) A ( ω n 2 ) ⋮ A ( ω n n − 1 ) ] \begin{bmatrix} a_0\\a_1\\ \vdots \\a_{n-1} \end{bmatrix}= \begin{bmatrix} (\omega_n^0)^0& (\omega_n^0)^1&(\omega_n^0)^2 &\cdots &(\omega_n^0)^{n-1}\\ (\omega_n^{-1})^0& (\omega_n^{-1})^1&(\omega_n^{-1})^2&\cdots &(\omega_n^{-1})^{n-1}\\ \vdots&\vdots &\vdots &\ddots &\vdots \\ (\omega_n^{-(n-1)})^0 & (\omega_n^{-(n-1)})^1& (\omega_n^{-(n-1)})^2&\cdots & (\omega_n^{-(n-1)})^{n-1} \end{bmatrix} \times \begin{bmatrix} A(\omega_n^0)\\ A(\omega_n^1)\\ A(\omega_n^2)\\ \vdots \\ A(\omega_n^{n-1})\\ \end{bmatrix} ⎣⎢⎢⎢⎡​a0​a1​⋮an−1​​⎦⎥⎥⎥⎤​=⎣⎢⎢⎢⎡​(ωn0​)0(ωn−1​)0⋮(ωn−(n−1)​)0​(ωn0​)1(ωn−1​)1⋮(ωn−(n−1)​)1​(ωn0​)2(ωn−1​)2⋮(ωn−(n−1)​)2​⋯⋯⋱⋯​(ωn0​)n−1(ωn−1​)n−1⋮(ωn−(n−1)​)n−1​⎦⎥⎥⎥⎤​×⎣⎢⎢⎢⎢⎢⎡​A(ωn0​)A(ωn1​)A(ωn2​)⋮A(ωnn−1​)​⎦⎥⎥⎥⎥⎥⎤​
这和 DFT 的操作很像,所以用 DFT 的过程实现 IDFT 即可。
负号?把 ω n 1 \omega_n^1 ωn1​ 改成 ω n − 1 \omega_n^{-1} ωn−1​ 即可;
1 n \frac{1}{n} n1​?做完之后再除个 n n n 即可。现在 IDFT 也是 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的了。
至此,所有的时间都是 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的了!即 FFT 的复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)!

5、实现问题

说是一回事,写是另一回事。
奇偶分组这个玩意就很坑,容易发现,设 r i r_i ri​ 为将 i i i 的高位翻转到低位得到的数字(如 0011 就变成 1100),那么初始位置为 i i i 的数就会被移动到 r i r_i ri​,所以我们可以预先完成移动,然后合并计算。时间就会加快很多了。
不过 FFT 本身常数巨大,主要因为 double 类型的计算时间,还有使用 sin ⁡ , cos ⁡ \sin,\cos sin,cos 函数带来的计算时间问题,所以常数问题一定要注意。
我们看到,DFT 做完后,得到的是将 n n n 次单位根代入后表达式的点值表示,IDFT 做完后,得到的是两多项式相乘的系数表示。
由于 FFT 涉及复数和除法,容易出现精度问题,所以考虑一种整数在模的前提下的 FFT,就出现了 FNT,也叫 NTT,即快速数论变换(Fast Number-theory Transform 或 Number Theory Transform)。这里有学习笔记……
如果我们计算卷积的时候 a , b a,b a,b 的下标不是相加为定值,而是一或二元逻辑运算(与,或,异或等等)后为定值,则可应用快速沃尔什变换(Fast Walsh Hadamard Transform)。学习笔记在这里
FFT真是大毒瘤……
FFT 和 FWT 都在图像处理,音频处理方面有较大应用。
FFT 的板子在这里,以 HDOJ1402 为例……Code
VijosP2000 那道题除了写 FFT 还得压位……或者用一种神奇的 O ( n 2 ) O(n^2) O(n2) 乘法:Code
终于把我的 flag 填完了我好开心啊!!!

FFT,快速傅里叶变换学习笔记 FFT,快速傅里叶变换描述问题计算两个n阶多项式的加法,需要Θ(n)\Theta(n)的时间。只需要将两式对应次数的系数相加即可。但是两个n阶多项式A、B相乘需要Θ(n2)\Theta(n^2)的时间,因为我们需要将A式的每一个系数乘上B式中每一个系数,在找次数相同的系数进行合并。我们希望加速多项式相乘的过程。多项式有两种表示法,系数表示法与点值表示法。系数表示法表示一个多项式A可以记为: A(x 阅读详情

相关推荐

FFT(快速傅里叶变换)算法学习笔记

FFT(快速傅里叶变换)算法学习笔记基本概念FFT(FastFourierTransformation)FFT (Fast Fourier Transformation)即快速傅里叶变换,是DFTDFT的加速算法,利用单位复数根的特殊性质,可以在Θ(nlogn)\Theta (nlogn)的时间内算出DFTDFT,利用相似性可以在同样的复杂度完成逆运算 DFT(DiscreteFourierTra

新的故事 旧的回忆 2万+

快速傅里叶变换(FFT)详解

快速傅里叶变换(FFT)详解   (这是我第一次写博,不喜勿喷...)   关于FFT已经听闻已久了,这次终于有机会在Function2的介绍下来了解一下FFT了。   快速傅里叶变换(Fast Fourier Transformation)简称FFT。在各大OI竞赛中也常有用到,也是一个十分优秀的可以装逼的好算法   在这篇blog中,有大量数学推导,因为我懒得写公式(好复杂,逃),所以...

u011555996的博客 4857

【学习笔记】极其美妙的算法——FFT(快速傅里叶变换)

文章目录前言FFT是什么?多项式表示法系数表示法点值表示法初步想法问题解决问题2复数定义运算复平面单位圆 前言 最近学会了FFT,一个极其美妙的算法! 众所周知FFT英文全称是 Fast Fast TLE Fast Fourier Transform FFT是什么? FFT(快速傅里叶变换)是DFT(离散傅里叶变换)的优化,用于加速多项式乘法。 即: 设 F(x)=∑i=0nfixiF(x)=\sum_{i=0}^nf_ix^iF(x)=∑i=0n​fi​xi , G(x)=∑i=0ngixiG(x)

LeeCongWei的博客 5098

快速傅里叶变换(FFT)的原理及公式

快速傅里叶变换(FFT)的原理及公式   非周期性连续时间信号x(t)的傅里叶变换可以表示为 式中计算出来的是信号x(t)的连续频谱。但是,在实际的控制系统中能够得到的是连续信号x(t)的离散采样值x(nT)。因此需要利用离散信号x(nT)来计算信号x(t)的频谱。   有限长离散信号x(n),n=0,1,…,N-1的DFT定义为:     可以看出,DFT需要计算大约N2次乘法...

weixin_33978016的博客 4947

快速傅里叶变换FFT学习笔记

文章目录问题背景前置知识 问题背景 多项式无论在信息学还是在数学上都有重要应用。在信息学竞赛中,经常需要借助多项式解决问题,涉及到关于多项式的各种运算。对于两个次数为 nnn 的多项式其中加减法均可以在 O(n)O(n)O(n) 内算完,而一般来说乘法需要 O(n2)O(n^2)O(n2) 来解决。但多项式乘法作为各种运算的基础,需要用更快的速度求出。 前置知识 ...

QQ82272760的博客 603

FFT(快速傅里叶变换)学习笔记

简介 FFTFFTFFT (法法塔)是个什么玩意?他的全名叫快速傅里叶变换(然而貌似和傅里叶并没有太大关系),用来快速求出多项式的点值表示,这个东西一般用来解决多项式相乘的问题。 一般的高精度乘法,我们有个 O(n2)O(n^2)O(n2) 的普及组做法,然而这个做法远远不能满足现代小学生的需求(传言小学生都会FFT)。于是我们要学习更优复杂度的做法,那就是复杂度为 O(nlogn)O(nlogn...

hipamp的博客 2046

简明FFT公式

本文清晰地罗列了傅里叶变换相关的公式,包括FT、IFT、DFT、IDFT、FFT、IFFT

weixin_50497501的博客 4299

快速傅里叶变换fft学习笔记

问题:给出两个多项式A=a0+a1x+a2x^2+......+anx^n;B=b0+b1x+b2x^2+......+bnx^n;求C=A*B。可知:c(i)=sigma(a(i)*b(k-i)),我们称之为卷积,对卷积暴力求解的复杂度为O(n^2),FFT可降低到O(nlogn)。通过补零操作可以将ABC三个多项式都统一为n-1次多项式一、点值表示如果x0,x1,x2......xn-1为互不...

mengbrirmb的博客 450

FFT算法

快速傅立叶变换(FFT)算法中的旋转因子是一个重要的概念,它有助于将信号从时间域转换到频率域,从而使频域分析变得更加高效。要理解旋转因子,首先需要了解傅立叶变换和FFT算法的基本原理。傅立叶变换是一种将信号从时间域转换到频率域的数学工具。它将一个时域信号分解成一系列正弦和余弦函数的频谱分量,以揭示信号中的频率信息。Xf∫−∞∞​xt⋅e−j2πftdt其中,Xf是频率域的表示,xt是时域的信号,f是频率,j是虚数单位。

weixin_63958646的博客 1963

基于Matlab与Bladed联合仿真的交互软件设计

基于Matlab与Bladed的交互软件设计

weixin_45014222的博客 816

python + QXDM5高通平台通过自动化截取log方法及代码

python + QXDM5高通平台通过自动化截取log方法及代码

dgzj2001的博客 1820

【学习笔记】快速傅里叶变换(FFT)

【学习笔记】快速傅里叶变换 学习之前先看懂这个 浅谈范德蒙德(Vandermonde)方阵的逆矩阵的求法以及快速傅里叶变换(FFT)中IDFT的原理——gzy hhh开个玩笑。 讲一下\(FFT\) 的流程,我也不准备长篇大论地分析\(FFT...\) 将系数表示法转换为点值表示法 \(O(n \log n)​\) 对于点值表示法直接进行操作 \(O(n)\) 将点值表示法转换为系数表示法 \(...

weixin_30432179的博客 386

Linux实战:rMATS可变剪切分析从零到一,避坑指南与结果深度解析

本文详细介绍了在Linux系统上从零开始部署rMATS进行可变剪切分析的完整流程,包括环境搭建、安装避坑指南、参数优化及结果解读。特别针对gfortran依赖、数学库配置等常见问题提供解决方案,并深入解析JC与JCEC结果的差异及可视化技巧,帮助生物信息学研究者高效完成可变剪切分析。

weixin_30394669的博客 410

快速傅里叶变换 FFT 学习笔记

文章目录FFT 学习笔记多项式:系数表示法:点值表示法:复数:前置芝士:向量:弧度制:定义:运算法则: FFT 学习笔记 本文有错误之处请诸位大佬多多指正! FFTFFTFFT :快速傅里叶变换的英文缩写,快速傅里叶变换是对离散傅里叶变换 DFTDFTDFT 的优化,用来解决多项式上的操作如 卷积 等问题。 多项式: 系数表示法: 一般在 初中 数学上,表示一个多项式我们用的是系数表示法 设 A(x)A(x)A(x) 表示一个关于xxx 的 nnn 次的多项式,那么: A(x)=∑i=0nai∗xiA(x)

天空之心 600

MicroLogix1400编程(使用RSLogix 500 + RSLinx Classic Lite)

MicroLogix1400编程

noscallion的博客 1万+

abaqus运行报错 WindowsError:[Error 2]

abaqus提交job总是提示“WindowsError [Error 2”,报这个错误,可能是由于安装其他软件改变了abaqus软件的路径导致,总结了看到的教程,按照下面的方法可以解决这个问题。 步骤一:找到你的abaqus安装路径(我是按照一个安装视频安装的,安装路径为SIMULI1),然后找到SIMULIA文件夹,点击进入后找到commands文件夹,将这个路径复制下来。 步骤二:我的电脑右键属性,在左侧中找到高级系统设置并...

az101za的博客 1万+

快速傅里叶变换——FFT学习笔记

快速傅里叶变换——FFT,是一种加速多项式乘法运算的算法,其时间复杂度为 O(nlogn) ,本文不涉及该算法的数学推导过程,仅讲解其核心思想和具体实现。

m0_51983846的博客 1219

ArcGIS License Server点击启动没反应,许可管理器无法启动怎么办

4 当我们再打开ArcGIS License Server Administrator的时候。3 在【服务】中找到【ArcGIS License Manager】双击。无法启动ArcGIS License Server的情况。在使用ArcGIS的过程中,我们经常会遇到。专注GIS领域知识分享,交流行业软件技巧。欢迎关注,不定期分享GIS各种问题和技巧。1 右击我的电脑——【管理】服务状态——启动,确定即可。启动类型选择——自动。

GIS蒲公英的博客 2万+

FFT 快速傅里叶变换 学习笔记

FFT 快速傅里叶变换 前言 lmc,ikka,attack等众多大佬都没教会的我终于要自己填坑了。 又是机房里最后一个学fft的人 用处 多项式乘法 卷积 \(g(x)=a_0+a_1x+a_2x^2\) \(f(x)=b_0+b_1x+b_2x^2\) 他们的乘积c(x)就是 \(c(x)=a_0b_0+a_0b_1x+a_0b_2x^2+a_1b_0x+a_1b_1x^2+a_1b...

weixin_30650859的博客 133

实战:RK3568 Android14 调试 MIPI DSI 液晶屏

LCD1_RST -> 对应原理图网络连接到 GPIO。LCD1_PWR_EN ->用于给屏幕 VCC 供电。LCD0_BL_EN / LCD0_BL_PWM -> MP3302 升压芯片驱动 LED 灯条。![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/100f2be7f763494da1032464e272e63b.png&pinctrl {/* 配置 LCD_RST 和 LCD_EN */

qq_33427070的博客 1549

5G无人机安全研究综述

国内多所高校提出混合信任模型,南京航空航天大学于2020年提出了起源信息感知的无人机网络信任模型[26],模型基于报文的完整性对报文创建和操作节点的行为评判并生成观测证据,收集证据进行信任评估,识别网络中的恶意节点并进行路由隔离,实现准确的对等信任评估。同时,5G技术的高速率、高可靠性、低时延等特点,能够为无人机提供实时高清图像回传,保证通信网络的稳定,拓展无人机飞控距离限制,丰富了5G无人机的应用场景。5G和无人机技术的融合,丰富了传统无人机的应用服务场景,然而5G无人机仍存在安全隐患。

weixin_70923796的博客 765

FFT学习笔记(快速傅里叶变换)

**快速傅里叶变换(Fast Fourier Transformation,简称FFT)** 一般用来加速多项式乘法。求两个$n$次多项式相乘,朴素算法需要$O(n^2)$,但FFT只需要$O(n\log n)$就能解决。

tanjunming2020的博客 2826

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【算法竞赛学习笔记】快速傅里叶变换FFT-数学提高计划

tilte : 快速傅里叶变换FFT学习笔记 tags : ACM,数论 date : 2021-7-18 简介 FFT(Fast Fourier Transformation),中文名快速傅里叶变换,用来加速多项式乘法。 DFT,中文名离散傅里叶变换,用来把多项式转化成离散的点。 IDFT,中文名离散傅里叶反变换,用来把离散的点还原成多项式。 时间复杂度O(nlogn) 将一个用系数表示的多项式转换成它的点值表示的算法。 系数表示法: f(x)={a0,a1,a2,...,an−1}f(x)=\{.

SC_Linno的博客 652

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【学习笔记】超简单的快速傅里叶变换(FFT)(含全套证明)

整理的算法模板合集: ACM模板 目录多项式复数复数的单位根 / 单位向量离散傅里叶变换(DTF)离散傅里叶逆变换(IDTF)FFT算法整体流程代码实现递归版迭代版“三步变两步”优化P1919 【模板】FFT快速傅里叶变换 学习笔记(用ipad记录的笔记): 超级简单的快速傅里叶变换!只要基础够扎实,顺着推一遍没有什么难以理解的,我学的整个过程没有一点卡壳,真的很爽,整整写了三个小时,写了满满6页的笔记。主要是内容太多了。 首先是一些基础概念: 多项式 复数 复数的单位根 / 单位向量 离散傅里叶变

繁凡さん的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

上一篇: [KDTree] [优先队列] [HDU4347] The Closest M Points
下一篇: [NTT] 快速数论变换学习笔记
HeRaNO
博客等级 码龄11年 67粉丝 100原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值