埋了一天的算導就當我看懂了?
目前僅限於學到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 如果要求他們的積,則需...