-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathfft.cpp
67 lines (54 loc) · 1.85 KB
/
fft.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
struct base {
double a, b;
base(double _a = 0, double _b = 0) : a(_a), b(_b) { }
const base operator+(const base &c) const { return base(a + c.a, b + c.b); }
const base operator-(const base &c) const { return base(a - c.a, b - c.b); }
const base operator*(const base &c) const {
return base(a * c.a - b * c.b, a * c.b + b * c.a);
}
};
using poly = vector<base>;
const double PI = acos(-1);
void fft(poly &a, bool inv = 0) {
int n = (int)a.size();
for (int i = 0; i < n; i++) {
int bit = n >> 1, j = 0, k = i;
while (bit > 0) {
if (k & 1) j += bit;
k >>= 1, bit >>= 1;
}
if (i < j) swap(a[i], a[j]);
}
double angle = 2 * PI / n * (inv ? -1 : 1);
poly wn(n / 2);
for (int i = 0; i < n / 2; i++) wn[i] = {cos(angle * i), sin(angle * i)};
for (int len = 2; len <= n; len <<= 1) {
int aux = len / 2;
int step = n / len;
for (int i = 0; i < n; i += len) {
for (int j = 0; j < aux; j++) {
base v = a[i + j + aux] * wn[step * j];
a[i + j + aux] = a[i + j] - v;
a[i + j] = a[i + j] + v;
}
}
}
for (int i = 0; inv && i < n; i++) a[i].a /= n, a[i].b /= n;
}
vector<ll> multiply(vector<ll> &ta, vector<ll> &tb) {
int n = (int)ta.size(), m = (int)tb.size();
int t = n + m - 1, sz = 1;
while (sz < t) sz <<= 1;
poly a(sz), b(sz), c(sz);
for (int i = 0; i < sz; i++) {
a[i] = i < n ? base((double)ta[i]) : base(0);
b[i] = i < m ? base((double)tb[i]) : base(0);
}
fft(a, 0), fft(b, 0);
for (int i = 0; i < sz; i++) c[i] = a[i] * b[i];
fft(c, 1);
vector<ll> res(sz);
for (int i = 0; i < sz; i++) res[i] = ll(round(c[i].a));
while ((int)res.size() > t && res.back() == 0) res.pop_back();
return res;
}