template <typename Container> voidFFT(int T, Container &A, int type) { staticint Rev[N]; for (int i = 0; i < T; i ++) Rev[i] = (Rev[i >> 1] >> 1) | (i & 1 ? T >> 1 : 0); for (int i = 0; i < T; i ++) if (i < Rev[i]) swap(A[i], A[Rev[i]]); for (int cur = 1; cur < T; cur <<= 1) { Complex base(cos(PI / cur), sin(PI / cur) * type);
static Complex comp[N]; comp[0] = Complex(1, 0); for (int i = 1; i < cur; i ++) comp[i] = comp[i - 1] * base;
for (int L = 0; L < T; L += cur << 1) for (int j = 0; j < cur; j ++) { Complex tempx = A[L | j], tempy = comp[j] * A[L | j | cur]; A[L | j] = tempx + tempy, A[L | j | cur] = tempx - tempy; } }
if (type == 1) return; for (int i = 0; i < T; i ++) A[i].a /= T; } // void FFT(int T, Complex *A, int type) // { // vector<Complex> temp(A, A + T); // FFT(T, temp, type); // copy(temp.begin(), temp.end(), A); // }
constint mod = 998244353, ord = 3, ordinv = 332748118;
inlineintksm(int base, int k) { int res = 1; while (k) { if (k & 1) res = res * base % mod; base = base * base % mod, k >>= 1; } return res; }
template <typename Container> voidNTT(int T, Container &A, int type) { staticint Rev[N]; for (int i = 0; i < T; i ++) Rev[i] = (Rev[i >> 1] >> 1) | (i & 1 ? T >> 1 : 0); for (int i = 0; i < T; i ++) if (i < Rev[i]) swap(A[i], A[Rev[i]]);
for (int cur = 1; cur < T; cur <<= 1) { int base = ksm(type == 1 ? ord : ordinv, (mod - 1) / (cur << 1));
staticint comp[N]; for (int i = comp[0] = 1; i < cur; i ++) comp[i] = comp[i - 1] * base % mod;
for (int L = 0; L < T; L += cur << 1) for (int j = 0; j < cur; j ++) { int tempx = A[L | j], tempy = comp[j] * A[L | j | cur] % mod; A[L | j] = (tempx + tempy) % mod, A[L | j | cur] = (tempx - tempy + mod) % mod; } }
if (type == 1) return; for (int i = 0, inv = ksm(T, mod - 2); i < T; i ++) A[i] = A[i] * inv % mod; } voidNTT(int T, int *A, int type) { vector<int> temp(A, A + T); NTT(T, temp, type); copy(temp.begin(), temp.end(), A); }
乘法函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
template<typename Container> Container multi(int T, Container &F, Container &G) { Container A(F), B(G), H(T); NTT(T, A, 1), NTT(T, B, 1); for (int i = 0; i < T; i ++) H[i] = A[i] * B[i] % mod; NTT(T, H, -1); return H; } vector<int> multi(int T, int *F, int *G) { vector<int> A(F, F + T), B(G, G + T); returnmulti(T, A, B); }
// while (T <= n << 1) T <<= 1; voiddivide(int T, vector<int> &F, vector<int> &G, vector<int> &Q, vector<int> &R) { vector<int> A(F), B(G); reverse(A.begin(), A.begin() + n + 1), reverse(B.begin(), B.begin() + m + 1); getinv(T, B, Q), B = Q; for (int i = n + 1; i < T; i ++) B[i] = 0; NTT(T, A, 1), NTT(T, B, 1); for (int i = 0; i < T; i ++) Q[i] = A[i] * B[i] % mod; NTT(T, Q, -1); for (int i = n - m + 1; i < T; i ++) Q[i] = 0; reverse(Q.begin(), Q.begin() + n - m + 1);
B = G, R = Q; NTT(T, B, 1), NTT(T, R, 1); for (int i = 0; i < T; i ++) R[i] = R[i] * B[i] % mod; NTT(T, R, -1); for (int i = 0; i < m; i ++) R[i] = (F[i] - R[i] + mod) % mod; }