题解 P4245 【【模板】MTT】

panda_2134

2018-03-07 08:29:37

Solution

其实这个题卡精度来着……我也没想到要开long double才能过……因为数据是用ddd的模板做的,他用的好像是合并dft精度比较高来着QAQ 其实就是把每个数拆成 $a \cdot 32768 + b$ 的形式,然后乘起来再展开就可以了。当然你想要NTT合并也行qwq 代码如下: ```cpp #include <bits/stdc++.h> typedef long long int64; typedef long double D; int MOD; const int MAXN = 524288; const D PI = acos(-1); struct complex { D real, imag; complex() { real = imag = 0; } complex(D x): real(x), imag(0) {} complex(D x, D y): real(x), imag(y) {} inline complex conj() { return complex(real, -imag); } inline complex operator+(complex rhs) const { return complex(real + rhs.real, imag + rhs.imag); } inline complex operator-(complex rhs) const { return complex(real - rhs.real, imag - rhs.imag); } inline complex operator*(complex rhs) const { return complex(real * rhs.real - imag * rhs.imag, imag * rhs.real + real * rhs.imag); } inline complex operator*=(complex rhs) { return (*this) = (*this) * rhs; } //(a+bi)(c+di) = (ac-bd) + (bc+ad)i friend inline complex operator*(D x, complex cp) { return complex(x * cp.real, x * cp.imag); } inline complex operator/(D x) const { return complex(real / x, imag / x); } inline complex operator/=(D x) { return (*this) = (*this) / x; } friend inline complex operator/(D x, complex cp) { return x * cp.conj() / (cp.real * cp.real - cp.imag * cp.imag); } inline complex operator/(complex rhs) const { return (*this) * rhs.conj() / (rhs.real * rhs.real - rhs.imag * rhs.imag); } inline complex operator/=(complex rhs) { return (*this) = (*this) / rhs; } inline D length() { return sqrt(real * real + imag * imag); } }; inline complex get_omega(int len, bool inv) { return inv ? complex(std::cos(2*PI / len), -std::sin(2*PI / len)) :complex(std::cos(2*PI / len), std::sin(2*PI / len)); } inline void fft(int len, complex* A, bool inv = false) { static int R[MAXN+10]; for(int i = 0; i < len; i++) R[i] = ((R[i>>1]>>1) | (len >> (i&1))) & (len-1); for(int i = 0; i < len; i++) if(R[i] > i) std::swap(A[i], A[R[i]]); for(int step = 1; step < len; step <<= 1) for(int i = 0; i < len; i += (step<<1)) { complex omega = 1, t = 0, rt = get_omega(step<<1, inv); for(int j = 0; j < step; j++, omega *= rt) { t = A[i+j+step] * omega; A[i+j+step] = A[i+j] - t; A[i+j] = A[i+j] + t; } } if(inv) for(int i = 0; i < len; i++) A[i] /= len; } void mtt(int deg, int *lhs, int *rhs, int *ret) { static complex A[MAXN+10], B[MAXN+10], C[MAXN+10], D[MAXN+10], E[MAXN+10], F[MAXN+10], G[MAXN+10], H[MAXN+10]; int len; for(len = 1; len <= 2*deg; len<<=1); for(int i = 0; i < len; i++) { lhs[i] %= MOD; rhs[i] %= MOD; A[i] = lhs[i] >> 15; B[i] = lhs[i] & 0x7fff; C[i] = rhs[i] >> 15; D[i] = rhs[i] & 0x7fff; } fft(len, A); fft(len, B); fft(len, C); fft(len, D); for(int i = 0; i < len; i++) { E[i] = A[i] * C[i]; F[i] = B[i] * C[i]; G[i] = A[i] * D[i]; H[i] = B[i] * D[i]; } fft(len, E, true); fft(len, F, true); fft(len, G, true); fft(len, H, true); for(int i = 0; i < len; i++) ret[i] = (((int64(round(E[i].real)) % MOD)<<30) % MOD + ((int64(round(F[i].real)) % MOD)<<15) % MOD + ((int64(round(G[i].real)) % MOD)<<15) % MOD + int64(round(H[i].real)) % MOD) % MOD; } int deg, n, m, F[MAXN+10], G[MAXN+10], H[MAXN+10]; inline int readint() { int f=1, r=0; char c=getchar(); while(!isdigit(c)) { if(c=='-')f=-1; c=getchar(); } while(isdigit(c)) { r=r*10+c-'0'; c=getchar(); } return f*r; } int main() { n = readint(); m = readint(); MOD = readint(); for(int i = 0; i <= n; i++) F[i] = readint(); for(int i = 0; i <= m; i++) G[i] = readint(); mtt(std::max(n, m), F, G, H); for(int i = 0; i <= n + m; i++) printf("%d ", H[i]); } ```