板子
NTT
int R[MAXN], W[MAXN];
void Init(int len) {
for (int i = 1; i < len; ++i) {
R[i] = (R[i >> 1] >> 1) | (i & 1 ? (len >> 1) : 0);
}
int wn = Ksm(G, (MOD - 1) / len);
W[len >> 1] = 1;
for (int i = (len >> 1) + 1; i < len; ++i) {
W[i] = (long long) W[i - 1] * wn % MOD;
}
for (int i = (len >> 1) - 1; i > 0; --i) {
W[i] = W[i << 1];
}
return;
}
inline int GetLimit(int n) {
return 1 << (32 - __builtin_clz(n));
}
void Ntt(int *F, int limit, int type) {
static unsigned long long c[MAXN];
copy(F, F + limit, c);
for (int i = 1; i < limit; ++i) {
if (i < R[i]) {
swap(c[i], c[R[i]]);
}
}
for (int o = 2, j = 1; o <= limit; o <<= 1, j <<= 1) {
for (int i = 0; i < limit; i += o) {
for (int k = 0; k < j; ++k) {
unsigned long long OI = c[i + j + k] * W[k + j] % MOD;
c[i + j + k] = c[i + k] + MOD - OI;
c[i + k] += OI;
}
}
}
if (type == -1) {
reverse(c + 1, c + limit);
int inv = Ksm(limit, MOD - 2);
for (int i = 0; i < limit; ++i) {
c[i] = c[i] % MOD * inv % MOD;
}
}
for (int i = 0; i < limit; ++i) {
F[i] = c[i] % MOD;
}
return;
}