本文不做證明,詳細證明請看如上資料。
fft在演算法競賽中主要用來加速多項式的乘法
普通是多項式乘法時間複雜度的是o(n2),而用fft求多項式的乘法可以使時間複雜度達到o(nlogn)
fft求多項式的乘法步驟主要如下圖
其中求值是將係數表達轉換成點值表達,帶入的自變數是wn=1的複數解,稱為dft
插值是將點值表達轉換成係數表達,稱為dft-1
dft 和 dft-1都可以用fft加速實現
這是遞迴版的fft
還有一種非遞迴的版本
我們發現葉子節點的下表的二進位制為:000 100 010 110 001 101 110 111
與它們的本身所對應的位置的二進位制:000 001 010 011 100 101 011 111
相反所以我們可以確定葉子節點的值,從下往上進行操作
求二進位制反轉的**(其中l是二進位制位):
for (int i = 0; i < n; i++)假設現在r[i]的二進位制是abcd,沒有操作之前的r[i>>1]是0abc,操作之後的是cba0,再右移是0cba,再判斷原來的d是不是1在最高位放1或0,就剛好是反轉的結果
模板:遞迴版(以求大數乘法為例):
#includeusingfft非遞迴版模板:namespace
std;
#define fi first
#define se second
#define pi acos(-1.0)
#define ll long long
#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ull unsigned ll
#define pll pair#define pii pair#define piii pair#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
typedef complex
cd;const
int n = 2e5 + 5
;char
a[n], b[n];
cd a[n], b[n];
inttmp[n];
void fft(cd *x, int n, int
type)
fft(l, n>>1
, type);
fft(r, n>>1
, type);
cd wn(cos(
2*pi/n), sin(type*2*pi/n)), w(1, 0
), t;
for(int i = 0; i < n>>1; i++, w *=wn)
}int
main()
inti;
for (i = m; i >= 1; i--) if(tmp[i]) break
;
for (i; i >= 0; i--) printf("%d"
, tmp[i]);
printf("\n
");}
return0;
}
typedef complexcd;ps:手寫complex類+非遞迴版最快const
int n = 2e5 + 5
;cd a[n], b[n];
intr[n];
void fft(cd *x, int n, int
type) }}
if(type == -1) }
intmain()
ntt模板:
#includeusing任意模數ntt模板:namespace
std;
/*469762049--3
998244353--3
1004535809--3
1e9+7 -- 5
(g 是mod(r*2^k+1)的原根)
素數 r k g
3 1 1 2
5 1 2 2
17 1 4 3
97 3 5 5
193 3 6 5
257 1 8 3
7681 15 9 17
12289 3 12 11
40961 5 13 3
65537 1 16 3
786433 3 18 10
5767169 11 19 3
7340033 7 20 3
23068673 11 21 3
104857601 25 22 3
167772161 5 25 3
469762049 7 26 3
1004535809 479 21 3
2013265921 15 27 31
2281701377 17 27 3
3221225473 3 30 5
75161927681 35 31 3
77309411329 9 33 7
*/const
int n = 300100, p = 998244353
;inline
int qpow(int x, int
y)
return
res;
}int
r[n];
void ntt(int *x, int n, int
opt)
}}
if (opt == -1) }
inta[n], b[n], c[n];
intmain()
constint maxn = 400005,maxm = 100005
;int pr=;
intr[maxn];
inline ll qpow(ll a,ll b,ll p)
struct
fft }
}if (f == 1) return
;
int nv = qpow(n,p - 2,p); reverse(a + 1,a +n);
for (int i = 0; i < n; i++) a[i] = 1ll * a[i] * nv %p;
}}fft[3];
intf[maxn],g[maxn],b[maxn],deg1,deg2,deg,md;
ll ans[maxn];
ll inv(ll n,ll p)
ll mul(ll a,ll b,ll p)
void
crt()
}void
conv()
}int
main()
FFT NTT 學習筆記
顯然因為我不會數學,所以這篇文章會非常 感性 將兩個多項式乘起來,即求 f g h 多項式的項數 n le10 5 複數複數是指形如 x yi 的數,高中會教。它的四則運算法則是這樣的 令 p,q 為兩個複數 p pm q x p pm x q y p pm y q i p times q x px...
FFT NTT數學解釋
fft和ntt真是噩夢呢 既然被fft和ntt坑夠了,坑一下其他的人也未嘗不可呢 設有乙個數a,使得an 1,其中n為滿足an 1的最小正整數 滿足條件的a有哪些呢?更寬泛地說,只要在乙個集合中定義了加法和乘法,而且二者滿足 這些基本上是小學學的吧,除了最後一點之外,其他都是廢話 那麼裡面滿足an ...
FFT NTT中檔題總結
被deepinc 怕了,把一些題放到這裡來 其實這道題放到中檔題也不太合適,個人感覺真的很難,機房裡好像都是頹的題解 因為期望的可加性,把每個點的貢獻單獨處理,即求期望深度 考慮 y 對 x 的貢獻 當且僅當 x y 的路徑上第乙個點就選 y y 才能成為 x 的祖先 所以 y 對 x 的貢獻就是 ...