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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| #include <bits/stdc++.h> using LL = long long; const int N = 1 << 18 | 100, P = 998244353, G = 3, L = 1e5 + 1; using poly = std::vector<int>; void adj(int &x){ x += (x >> 31) & P; } int qpow(int x, int y = P - 2) { int res = 1; for (; y; y >>= 1, x = LL(x) * x % P) if (y & 1) res = LL(res) * x % P; return res; } namespace Poly { int r[N], iv[N]; void rdy(int &bit, int &tot, int len){ for (bit = 0, tot =1; tot < len + 1; tot <<= 1, ++bit); } void get_r(int bit, int tot){ for (int i = 1; i < tot; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (bit - 1)); } void ntt(int *x, int tot, int op) { static int gn[N]; for (int i = 1; i < tot; ++i) if (i < r[i]) std::swap(x[i], x[r[i]]); for (int mid = 1; mid < tot; mid <<= 1) { int g0 = qpow(G, (P - 1) / (mid << 1)); if (op == -1) g0 = qpow(g0); gn[0] = 1; for (int i = 1; i < mid; ++i) gn[i] = LL(gn[i - 1]) * g0 % P; for (int i = 0; i < tot; i += (mid << 1)) for (int *x1 = x + i, *x2 = x + i + mid, *ed = x2, *g = gn; x1 != ed; ++x1, ++x2, ++g) { int p = *x1, q = LL(*x2) * *g % P; adj(*x1 = p + q - P), adj(*x2 = p - q); } } if (op == 1) return ; int t = qpow(tot); for (int i = 0; i < tot; ++i) x[i] = LL(x[i]) * t % P; } poly operator * (poly x, poly y) { if (x.empty() || y.empty()) return {}; int n = x.size(), m = y.size(), bit, tot; rdy(bit, tot, n + m), get_r(bit, tot); x.resize(tot), y.resize(tot); if (x != y) ntt(x.data(), tot, 1), ntt(y.data(), tot, 1); else ntt(x.data(), tot, 1), y = x; for (int i = 0; i < tot; ++i) x[i] = LL(x[i]) * y[i] % P; ntt(x.data(), tot, -1), x.resize(n + m - 1); return x; } poly operator - (poly x, poly y) { if (x.size() < y.size()) x.resize(y.size()); for (int i = y.size() - 1; ~i; --i) adj(x[i] -= y[i]); return x; } poly inv(poly x) { int n = x.size(); if (n == 1) return {qpow(x[0])}; int bit, tot; rdy(bit, tot, n << 1); poly y = inv(poly(x.begin(), x.begin() + ((n + 1) >> 1))), z = y * y * x, res(n); y.resize(n), z.resize(n); for (int i = 0; i < n; ++i) adj(res[i] = 2ll * y[i] - z[i]); return res; } poly dif(poly x) { poly res(x.size() - 1); for (int i = x.size() - 1; i; --i) res[i - 1] = LL(i) * x[i] % P; return res; } poly inte(poly x) { poly res(x.size() + 1); if (!iv[1]) { iv[1] = 1; for (int i = 2; i < N; ++i) iv[i] = LL(P - P / i) * iv[P % i] % P; } for (int i = x.size(); i; --i) res[i] = LL(x[i - 1]) * iv[i] % P; return res; } poly ln(poly x) { poly res(dif(x) * inv(x)); res.resize(x.size()), res = inte(res); return res.resize(x.size()), res; } poly exp(poly x) { if (x.size() == 1) return {1}; int n = x.size(); poly y = exp(poly(x.begin(), x.begin() + ((n + 1) >> 1))); y.resize(n); poly z = ln(y); x = x - z, ++x[0]; return x = x * y, x.resize(n), x; } } int fac[N], ifac[N]; int main() { fac[0] = ifac[0] = fac[1] = ifac[1] = 1; for (int i = 2; i < L; ++i) fac[i] = LL(i) * fac[i - 1] % P; ifac[L - 1] = qpow(fac[L - 1]); for (int i = L - 2; i > 1; --i) ifac[i] = LL(i + 1) * ifac[i + 1] % P; poly f(L); for (int i = 1; i < L; ++i) f[i] = ifac[i]; poly g = Poly::exp(f); for (int i = 2; i < L; ++i) g[i] = LL(g[i]) * fac[i] % P; int T, n; for (scanf("%d", &T); T--; ) { scanf("%d", &n); printf("%d\n", g[n]); } return 0; }
|