快速傅利葉變換
關於fft網上的教材不多,而且大多與演算法問題關係不大。強烈推薦乙個。這個講得真的很不錯:從多項式乘法到快速傅利葉變換
本弱數學知識不夠多,複數、單位根之類的知識都是下午臨時補的。。。從下午開始看fft,看到晚上,總算大概是把遞迴版fft的思路看懂了吧。(迭代版的還沒看懂。。。有空慢慢鑽研)upd(2017.4.3):已經成功實現了迭代版,詳見這份**的下乙份**……
注意到idft的時候需要把所有單位根取倒數,那麼有乙個複數倒數式子:
設複數z=a+b i
那麼1/z=(a-bi) / [(a+bi)(a-bi)] =(a-bi) / (a²+b²) =a / (a²+b² ) - b i / (a²+b²)
然後我們發現單位根的a²+b²=sin²+cos²=1,所以只要變化連線a和bi的符號即可
遞迴版**打了注釋,以供日後觀賞學習
#include
#include
#define n 1000000
using
namespace
std;
struct
complex
complex
operator + (complex a)
complex
operator - (complex a)
complex
operator * (complex a)
complex
operator ^ (int f)//方便起見,我用異或表示是否取倒數
}a[n], b[n], w[n], temp[n];
const
double eps = 1e-2;
int l;
void fft(int n, complex buffer, int beg, int step, int f)
for(int i = 0; i < n; i++)
buffer[beg+i*step]=temp[i];
}void init_w(int n)
int main()
迭代版
做法思想都一樣,都是奇偶分類然後大力化簡……
和遞迴版不同的地方在於,遞迴版的分類是手動分組,通過每次設定step和beg來做。迭代版在剛開始就先把組分好了,然後就只要從下往上迭代直接做。
補充一下剛開始沒理解好的東西。
在迭代的過程中,設當前迭代塊的大小為
i ,則深度為n/
i,記n 個
n次單位根是wk
n,k=
0,1,
...,
n−1
此時陣列裡的區間[l
,l+i
−1] 的第k(
k=0,
1,..
.,i−
1)個位置的含義是,wk
n/i 在係數是al
,al+
1,..
.,al
+i−1
的情況下的求值答案(當然這裡的
a 是已經分組過的)。
最終迭代塊為
n,深度為
1 時就是答案。
兩邊用推出來的式子合併即可。
#include
#include
#include
#define n 400005
using
namespace
std;
namespace endless
;} complex
operator - (const
complex &that) const ;}
complex
operator * (const
complex &that) const ;}
}a[n], b[n], w[n], re_w[n];
const db pi = acos(-1.0);
int la, lb, n;
void init_w()
;re_w[i] = (complex);}}
void fft(complex *a, complex *w)
for(int i = 2; i <= n; i <<= 1)}}
}void main()
}int main()
UOJ 34 多項式乘法
統計這是一道模板題。給你兩個多項式,請輸出乘起來後的多項式。第一行兩個整數 n n 和 mm 分別表示兩個多項式的次數。第二行 n 1 n 1 個整數,分別表示第乙個多項式的 0 0 到 nn 次項前的係數。第三行 m 1 m 1 個整數,分別表示第乙個多項式的 0 0 到 mm 次項前的係數。一行...
UOJ 34 多項式乘法
fft模板 迭代的還沒會 先寫了個遞迴的 define的pi 我也是神了!少上一位就會wa 模板看的hzwer的 因為 pi較短 所以遞迴的跑的和迭代的一樣快 23333333 還差的幾點 1.acos要用 2.complex要自己寫 yts1999大爺說會被卡 3.要改成迭代的 1 include...
UOJ 34 多項式乘法
快速傅利葉變換模板題 演算法理解請看 演算法導論 第30章 多項式與快速傅利葉變換 至於證明插值唯一性什麼的看不懂也沒關係啦 只要明白這個過程是怎麼算的就ok。遞迴版 4252ms 23468kb 1 uoj 34 遞迴版 2 include3 include4 include5 include6 ...