多項式演算法 Part 5 分治FFT 學習筆記

2021-09-27 13:57:26 字數 1667 閱讀 3867

其他多項式演算法傳送門:

[多項式演算法](part 1)fft 快速傅利葉變換 學習筆記

[多項式演算法](part 2)ntt 快速數論變換 學習筆記

[多項式演算法](part 3)mtt 任意模數fft/ntt 學習筆記

[多項式演算法](part 4)fwt 快速沃爾什變換 學習筆記

分治fft是一種基於cdq分治(不是很懂和cdq有什麼關係)的演算法,主要用於在\(o(nlog^2n)\)的時間複雜度內計算以下內容:

給定數列\(g_1\sim g_\),求\(f_0\sim f_\),其中\(f_i\)滿足

\[ f_0=1\\ f_i=\sum_^jf_\times g_j \]

我們可以借鑑分治的思想,對於當前的\(f_l\sim f_r\),設\(mid=\lfloor\frac\rfloor\)

先遞迴計算\(f_l\sim f_\),接著考慮前半部分對後面的貢獻。

設對\(f_x(mid+1\le x\le r)\)的貢獻為\(w_x\),則有

\[ w_x=\sum_^f_i\times g_ \]

為了下面推導方便,把範圍擴大,設\(f_i=0(mid+1\le i\le r)\):

\[ w_x=\sum_^f_i\times g_\\ w_x=\sum_^f_\times g_ \]

此時設\(a_i=f_,b_i=g_\),則有:

\[ w_x=\sum_^a_i\times b_ \]

那麼就會發現這是乙個卷積的形式,使用fft計算即可。

好像挺簡單的?以前都沒敢學來著

例題: luogu p4721 【模板】分治 fft

這裡我使用ntt來實現演算法,當然使用fft也是沒有問題的。

加了io優化,**可能有點亂?

時間複雜度 \(o(nlog^2n)\)

空間複雜度 \(o(n)\)

// luogu-judger-enable-o2

#include #include #include #include #include #define rint register int

typedef long long ll;

//----- io optimize -----

#define getchar (p1==p2&&(p2=(p1=in)+fread(in,1,1<<20,stdin),p1==p2)?eof:*p1++)

char in[1<<20],*p1=in,*p2=in,ch,out[1<<21],*outp=out,st[15],*tp=st;

inline int getint(register int x=0)

inline void putint(int x,char c)

const int p=998244353,g1=3,g2=(p+1)/3;//g2為1/3 mod p

inline int add(int a,int b)

inline ll pow(ll a,ll b)

namespace poly

}int n,f[1<<18],g[1<<18];

int main()

{ n=getint(),f[0]=1;

for(rint i=1;i

分治fft還是比較簡單易懂的。

其中還有乙個小優化:對於遞迴到範圍較小的序列,直接暴力卷積,常數更小。

多項式演算法 Part 5 分治FFT 學習筆記

其他多項式演算法傳送門 多項式演算法 part 1 fft 快速傅利葉變換 學習筆記 多項式演算法 part 2 ntt 快速數論變換 學習筆記 多項式演算法 part 3 mtt 任意模數fft ntt 學習筆記 多項式演算法 part 4 fwt 快速沃爾什變換 學習筆記 分治fft是一種基於c...

我的演算法筆記(5)分治(1)

乙個臨時陣列 intmin int x,int y void merge int a,int s,int m,int e,int b 只要有乙個陣列的數全部都排完了,那麼我就可以吧另乙個陣列剩下的全部數就都放在臨時陣列裡了 while x1 m b x a x1 while x2 e b x a x...

作業5 分治演算法之最近對問題

最近對問題 令p為笛卡爾平面上n 1個點構成的集合。簡單起見,假設集合中每個點都不一樣。我們還假設這些點是按照其x周座標公升序排列的。為了更加方便,我們還按照點的y軸座標在另乙個列表中進行公升序排列,分別記為px,py。當2 n 3時,通過蠻力求解出d。當n 3時,可以利用點集在方向上的中位數mid...