这是我的 NTT,用时 1.24s。
#include<bits/stdc++.h>
using i64 = long long;
const i64 mod = 998244353, G = 3;
inline i64 qpow(i64 a, i64 b) {
i64 v = 1;
while (b) b & 1 && ((v *= a) %= mod), (a *= a) %= mod, b >>= 1;
return v;
}
const i64 invG = qpow(G, mod - 2);
const int maxn = 4e6 + 10;
inline i64 Mod(i64 x) {return x > mod ? x - mod : x;}
int rev[maxn];
i64 th[maxn];
inline void NTT(i64 *f, int n, bool isi) {
for (int i = 0; i < n; i++) i < rev[i] && (std::swap(f[i], f[rev[i]]), 1);
for (int l = 1, p = 2; p <= n; l <<= 1, p <<= 1) {
i64 I = qpow(isi ? invG : G, (mod - 1) / p);
th[0] = 1;
for (int i = 1; i < l; i++) th[i] = th[i - 1] * I % mod;
for (int s = 0; s < n; s += p) for (int t = 0; t < l; t++) {
i64 v = th[t] * f[s + l + t] % mod;
f[s + l + t] = Mod(f[s + t] - v + mod);
f[s + t] = Mod(f[s + t] + v);
}
}
}
i64 f[maxn], g[maxn];
int main() {
int n, m; scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++) scanf("%lld", &f[i]);
for (int i = 0; i <= m; i++) scanf("%lld", &g[i]);
for (m += n, n = 1; n <= m; n <<= 1);
for (int i = 1; i < n; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
NTT(f, n, 0), NTT(g, n, 0);
for (int i = 0; i < n; i++) (f[i] *= g[i]) %= mod;
NTT(f, n, 1);
i64 invn = qpow(n, mod - 2);
for (int i = 0; i <= m; i++) printf("%lld ", f[i] * invn % mod);
return 0;
}
如果把 22 23 行改为
f[s + l + t] = Mod(f[s + t] - v);
f[s + t] = Mod(f[s + t] + v);
用时 1.99s。
如果改为:
f[s + l + t] = Mod(f[s + t] - v);
f[s + t] = Mod(f[s + t] + v - mod);
用时 2.72s。
而这三部分的差距仅仅是 Mod 函数里第一种传入的都是正数,第二种一正一负,第三种都是负数。
每种都测了三四次,应该不是评测波动。
求问是为什么 QAQ。