快速傅利葉變換(FFT)

2021-09-08 10:34:42 字數 3848 閱讀 7399

埋了一天的算導就當我看懂了?

目前僅限於學到fft計算多項式係數向量的卷積,什麼頻域什麼東西的那些我都不懂。。。。

我就大概講一下?

首先我們對多項式的係數表達一般是這樣的:

$$\sum_^ a_i x^i$$

那麼這個多項式的次數界為n,最高次數為n-1

然後多項式的加減法很簡單,是$o(n)$可以計算的,而乘法不一樣,因為對於多項式$a(x)\times b(x)=c(x)$有

$$c(x)=\sum_^ c_i x^i$$

其中$$c_i=\sum_^i a_kb_$$

顯然$o(n^2)$

我們將這種係數表示法的係數用乙個a向量表示$a=(a_0, a_1, \cdots , a_)$,那麼我們算多項式乘法實際上只要算多項式係數就行了。

定義卷積

$$c = a \otimes b$$

a、b、c均為向量,而

$$c_i=\sum_^i a_kb_$$

其實就是這個定義卷積的定義。

接下來介紹一種很強大的表示方式,點值表示法

首先乙個次數界為n的多項式,一定能用n個點來表示出來(可以說是二維平面上的n個不同橫座標的點),多項式a的點值表示式即

$$\, y_)\}$$

其中$x_i$各不相同,且$y_k=a(x_k)$。而點值上多項式的加減法乘法都是o(n)的!(我都還沒證。。先用著吧。。)

對於兩個多項式$a$和$b$,運算後的多項式為$c$:

$$a=\), (x_1, y_), \cdots , (x_, y_)\}$$

$$b=\), (x_1, y_), \cdots , (x_, y_)\}$$

(注意$x_i$均對應相等!)

那麼$c$的點值表示為:

$$c=a+b=\+y_), (x_1, y_+y_), \cdots , (x_, y_+y_)\}$$

$$c=a-b=\-y_), (x_1, y_-y_), \cdots , (x_, y_-y_)\}$$

$$c=a \times b=\y_), (x_1, y_y_), \cdots , (x_, y_y_)\}$$

!!!都是$o(n)$的!!

但是我們發現其實乘法是有缺陷的,就是a次界的多項式乘b次界的多項式得到的多項式的次數界應該是a+b-1的。

但是我們不怕!我們可以擴充!我們將向量$a$和$b$的次數界擴充到a+b-1!係數用0補齊!而點值表示法則多加幾個點!

那麼就行了。。。。

那麼問題成功轉化為如何將係數表示法轉換到點值表示法,然後用o(n)解決它,然後再轉換回係數表示法。其中係數表示法轉換到點值表示法的操作叫求值運算,而點值轉換到係數的操作叫做插值運算。他們是有良定義的互逆運算!

而有一種方法稱作離散傅利葉變換(dft)的東西可以實現兩種操作,偉大的科學家發明了一種高效實現dft的演算法fft,總複雜度為$o(nlogn)$。無限仰膜orz

然後再介紹點複數吧。。最讓我感到神奇的是複數這個概念,,,好強大。。

複數的話我大概懂得這點?

複數有實部和虛部,其中虛部的單位是$i=$,定義為$e=a+bi$,帶$i$的是虛部

然後當虛部為0時,這個複數就是實數。。。(也就是說實數是複數的子集。。。。)

然後複數的運算是:當$x=a+bi, y=c+di$

$$x+y=(a+c)+(b+d)i$$

$$x-y=(a-c)+(b-d)i$$

$$x \times y=(a+bi)(c+di)=ac+adi+bci+bdi^2=(ac-bd)+(ad+bc)i$$

除法怎麼搞。。。。。。(以後補。。

然後我們定義複數冪:

$$e^=cos(u)+isin(u)$$

然後因為由於是指數,我們可以得到很好的性質。

關於複數還是詳見算導p511吧。。我不闡述了。。

fft的具體實現也看算導p513吧,,我也不闡述了。。。

關於fft的迭代優化我也不闡述了。。。。

然後本文介紹fft的東西就完結了。。

下邊是一些疑問與拓展:

我之前的疑問和暫時還有疑問的地方:

為什麼是用複數指數冪的形式?我的解釋是,,,因為根據複數冪定義能提供良好的相消引理。。這個很簡單吧。。

為什麼複數冪的形式是$e^=cos(u)+isin(u)$呢?因為週期性?

為什麼複數做x時,賦值到複數的實部?之前解釋過了,因為實數是複數的子集。

為什麼$dft^$後取的也是實部?同上

拓展:多維的fft:對於多維多項式:

$$y_=\sum_^ \sum_^ \cdots \sum_^ a_ \omega_^ \omega_^ \cdots \omega_^$$

我們可以對每一維單獨用fft求出,然後再帶入原式求下一維。認真體會。。

模板題:codevs:3123 高精度練習之超大整數乘法

將十進位制數看成多項式x=10,然後係數就是所有的數,然後用fft算出乘積後的係數後進製即可。

#include #include #include #include #include #include #include #include #include using namespace std;

typedef long long ll;

#define rep(i, n) for(int i=0; i<(n); ++i)

#define for1(i,a,n) for(int i=(a);i<=(n);++i)

#define for2(i,a,n) for(int i=(a);i<(n);++i)

#define for3(i,a,n) for(int i=(a);i>=(n);--i)

#define for4(i,a,n) for(int i=(a);i>(n);--i)

#define cc(i,a) memset(i,a,sizeof(i))

#define read(a) a=getint()

#define print(a) printf("%d", a)

#define dbg(x) cout << (#x) << " = " << (x) << endl

#define error(x) (!(x)?puts("error"):0)

inline const int getint()

#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)

struct cp

cp operator+ (const cp &x) const

cp operator- (const cp &x) const

cp operator* (const cp &x) const

};const int n=1000005;

const double pi=acos(-1.0);

int rev[n];

cp a[n];

void dft(cp *a, int n, int flag)

} }if(flag==-1) rep(i, n) a[i].r/=n;

}char s[n];

void readin(cp *a, int &n)

void init(int &n)

}cp a[n], b[n];

int n, len, ans[n];

int main()

其它例題:

【bzoj】2179: fft快速傅利葉(fft):同上,高精度裸題

【bzoj】3527: [zjoi2014]力(fft+卷積):注意卷積的形式

快速傅利葉變換FFT

fft的作用就不多說了,搞訊號處理的人都會用上。fft的由來 傅利葉變換ft 離散傅利葉變換dft 快速傅利葉變換fft。學習資料 1 陳後金的 數字訊號處理 裡面深入淺出,該有的公式都有,程式設計思想也有。2 一篇系統講述傅利葉變換的帖子 3 學生對fft的理解 4 工程人員對fft的簡單明瞭的總...

快速傅利葉變換 FFT

bzoj 2179 fft快速傅利葉 果題 bzoj2194 請計算c k sigma a i b i k 其中 k i n 並且有 n 10 5。a,b中的元素均為小於等於100的非負整數。注意到i 和 i k有奇妙的聯絡 不妨嘗試把b翻轉 然後就變成卷積了。貼個模板 include define...

快速傅利葉變換 FFT

首先說一下我用fft做什麼,我要做的是多項式乘法,或者說,加速多項式乘法。考慮多項式a x j 0n 1aj xj,它一共有 n 項,我們稱它的次數界為 n。假設我們有兩個次數界為 n 的多項式a x 和b x 要求它們的和是非常簡單的,只需要將對應的係數相加,複雜度為o n 如果要求他們的積,則需...