首先說一下我用fft做什麼,我要做的是多項式乘法,或者說,加速多項式乘法。
考慮多項式a(
x)=∑
j=0n
−1aj
xj,它一共有
n 項,我們稱它的次數界為
n。假設我們有兩個次數界為
n 的多項式a(
x)和b
(x) ,要求它們的和是非常簡單的,只需要將對應的係數相加,複雜度為o(
n)。如果要求他們的積,則需要將a(
x)的每一項和b(
x)的每一項相乘,複雜度為o(
n2) ,這就顯得有點慢了。
上面提到的多項式表示方法a(
x)=∑
j=0n
−1aj
xj稱為係數表示,實際上它還有另一種表示方法叫點值表示。我們取
n 個不同的值x0
,x1 ,…,xn
−1代入多項式,可以得到
n 個點(x
0,a(
x0))
,…,(xn
−1,a
(xn−
1)) 。這
n 個點可以確定乙個唯一的原多項式(至於為什麼,就不細說了)。
假設我們可以迅速在多項式的係數表示和點值表示間轉換,就可以迅速完成多項式乘法。回到那個多項式a(
x),我們把
x 的取值範圍擴充套件到複數,ωn
表示n(假設為2的整數冪)次單位複數根,恰當地選擇多項式中
x的取值,使其分別等於ω1
n,ω2
n,..
.,ωn
n ,就可以利用一些性質,遞迴地計算,進行加速。
下面放出一道題:thief in a shop
可以這樣理解題意:有
n 個數a1
~an ,從中選取
k 個(可重複),問得到的和可以是多少。我們可以把它轉化為乙個多項式,若存在ai
,則多項式第ai
項的係數為
1 ,否則為
0。這樣一來,兩個多項式的乘積中,係數不為
0 的項就是k=
2時的解,繼續乘下去,可以得到k=
3,4,
5...
的解。
於是,我們就需要fft來迅速完成多項式乘法,同時利用倍增,只進行lo
g2(k
) 次乘法。注意每次乘完之後,要對那個列向量規整一下,避免迭代過程累積誤差。
下面的**可以作為模板。。
#include
using
namespace
std;
#define ll long long
const
double eps = 0.5;
const
double pi = acos(-1.0);
struct complex
complex operator+(const complex& c)const
complex operator-(const complex& c)const
complex operator*(const complex& c)const
};void change(complex y,int len)
if(jvoid fft(complex y,int len,int on)}}
if(on == -1)
int fix(complex *y,int l)else
c.i = 0;
}for(int i=l;i<1024*1024;i++)
return l+1;
}void print(complex *y,int l)
}cout
l1 = l2 = sz;
fft(v1,l1,1);
fft(v2,l2,1);
for(int i=0;i1);
return sz;
}complex v[1024*1024];
complex v2[1024*1024];
complex ans[1024*1024];
int main()
int sz = 1024;
ans[0].r = 1;
while(k)
sz = fix(ans,sz);
for(int i=0;iif(ans[i].r > eps)
}return
0;}
快速傅利葉變換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(快速傅利葉變換)
大佬部落格 hdu 4609 題意 給定乙個陣列,問從其中選3個值能構成三角形的概率是多少。思路 先求出選兩個之和的情況,然後列舉選取的最長邊,根據三角形的三邊定理來求解。選兩個之和的情況及是,先將長度相同的統計起來,然後求這個陣列的卷積,其值就是和為i的有多少個,也就是 中的num陣列。這裡解釋一...