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
| #define LDB long double class COMP{ public: LDB x, y; COMP operator + (const COMP &o) const{ COMP r = *this; r.x += o.x, r.y += o.y; return r; } COMP operator - (const COMP &o) const{ COMP r = *this; r.x -= o.x, r.y -= o.y; return r; } COMP operator * (const COMP &o) const{ COMP r; r.x = x * o.x - y * o.y, r.y = x * o.y + y * o.x; return r; } } ; COMP mk(LDB a, LDB b) {COMP o; o.x = a, o.y = b; return o;} COMP conj(COMP o) {o.y = -o.y; return o;} int rev[CN << 2]; void cg(COMP t[], int n){ for(int i = 0; i < n; i++) rev[i] = (rev[i >> 1] >> 1) + (i & 1) * (n >> 1); for(int i = 0; i < n; i++) if(i < rev[i]) swap(t[i], t[rev[i]]); } void fft(COMP t[], int n, int tp){ cg(t, n); for(int w = 2; w <= n; w <<= 1){ int l = w >> 1; COMP gn = mk(cos(2 * PI / (LDB)w), sin(2 * tp * PI / (LDB)w)); for(int i = 0; i < n; i += w){ COMP g = mk(1, 0); for(int j = i; j < i + l; j++){ COMP u = t[j], v = t[j + l] * g; t[j] = u + v, t[j + l] = u - v, g = g * gn; } } } if(tp ^ 1){ for(int i = 0; i < n; i++) t[i].x /= (LDB)n, t[i].y /= (LDB)n; } } COMP p[CN << 2], q[CN << 2], x[CN << 2], y[CN << 2], z[CN << 2], w[CN << 2]; void conv(int a[], int b[], int n){ int B = (1 << 15) - 1, N = 1; while(N < (n << 1)) N <<= 1; for(int i = 0; i < n; i++) p[i] = mk(a[i] >> 15, a[i] & B); for(int i = 0; i < n; i++) q[i] = mk(b[i] >> 15, b[i] & B); fft(p, N, 1), fft(q, N, 1); for(int i = 0; i < N; i++){ int j = (N - 1) & (N - i); COMP k1, r1, k2, r2; k1 = (p[i] + conj(p[j])) * mk(0.5, 0); r1 = (p[i] - conj(p[j])) * mk(0, -0.5); k2 = (q[i] + conj(q[j])) * mk(0.5, 0); r2 = (q[i] - conj(q[j])) * mk(0, -0.5); x[i] = k1 * k2, y[i] = r1 * r2, z[i] = k1 * r2, w[i] = k2 * r1; } for(int i = 0; i < N; i++) p[i] = x[i] + y[i] * mk(0, 1); for(int i = 0; i < N; i++) q[i] = z[i] + w[i] * mk(0, 1); fft(p, N, -1), fft(q, N, -1); for(int i = 0; i < N; i++){ LL X = (LL)(0.5 + p[i].x), Y = (LL)(0.5 + p[i].y), Z = (LL)(0.5 + q[i].x), W = (LL)(0.5 + q[i].y); X = (X % P + P) % P, Y = (Y % P + P) % P, Z = (Z % P + P) % P, W = add((W % P + P) % P, Z); a[i] = add((X << 30) % P, add((W << 15) % P, Y)); } }
|