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 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| #include <bits/stdc++.h> using LL = long long; const int P = 998244353, G = 3, N = 1e6 + 100, L = 1e5 + 1; 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; } void adj(int &x){ x += (x >> 31) & P; } namespace Poly { int r[N]; void rdy(int &bit, int &tot, int len){ for (tot = 1, bit = 0; tot < len + 1; tot <<= 1, ++bit); } void get_r(int bit, int tot){ for (int i = 0; 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 = x1 + 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; } void inv(int *x, int *y, int len) { if (len == 1) return void(y[0] = qpow(x[0])); inv(x, y, (len + 1) >> 1); int bit, tot; static int t[N]; rdy(bit, tot, len << 1), get_r(bit, tot); std::fill(y + ((len + 1) >> 1), y + tot, 0); std::copy(x, x + len, t); std::fill(t + len, t + tot, 0); ntt(t, tot, 1), ntt(y, tot, 1); for (int i = 0, tt; i < tot; ++i) { adj(tt = 2 - LL(t[i]) * y[i] % P); y[i] = LL(tt) * y[i] % P; } ntt(y, tot, -1); std::fill(y + len, y + tot, 0); } void dif(int *x, int *y, int len) { for (int i = 1; i < len; ++i) y[i - 1] = LL(x[i]) * i % P; y[len - 1] = 0; } void inte(int *x, int *y, int len) { for (int i = 1; i < len; ++i) y[i] = LL(x[i - 1]) * qpow(i) % P; y[0] = 0; } void ln(int *x, int *y, int len) { static int a[N], b[N]; dif(x, a, len); inv(x, b, len); int bit, tot; rdy(bit, tot, len << 1), get_r(bit, tot); std::fill(a + len, a + tot, 0); std::fill(b + len, b + tot, 0); ntt(a, tot, 1), ntt(b, tot, 1); for (int i = 0; i < tot; ++i) a[i] = LL(a[i]) * b[i] % P; ntt(a, tot, -1); std::fill(a + len, a + tot, 0); inte(a, y, len); std::fill(y + len, y + tot, 0); } void exp(int *x, int *y, int len) { if (len == 1) return void(y[0] = 1); exp(x, y, (len + 1) >> 1); int bit, tot; static int t[N]; rdy(bit, tot, len << 1); std::fill(t, t + tot, 0); ln(y, t, len); get_r(bit, tot); adj(t[0] = x[0] + 1 - t[0]); for (int i = 1; i < len; ++i) adj(t[i] = x[i] - t[i]); std::fill(t + len, t + tot, 0); ntt(t, tot, 1), ntt(y, tot, 1); for (int i = 0; i < tot; ++i) y[i] = LL(y[i]) * t[i] % P; ntt(y, tot, -1); std::fill(y + len, y + tot, 0);
} void sqrt(int *x, int *y, int len) { static int t[N]; ln(x, t, len); for (int i = 0; i < len; ++i) t[i] = LL((P + 1) >> 1) * t[i] % P; exp(t, y, len); } void pow2(int *x, int *y, int len) { int bit, tot; rdy(bit, tot, len << 1), get_r(bit, tot); ntt(x, tot, 1); for (int i = 0; i < tot; ++i) y[i] = LL(x[i]) * x[i] % P; ntt(y, tot, -1); std::fill(y + len, y + tot, 0); } } int h[N], a[N], g[N]; int fac[N], ifac[N]; int calc(int x){ return qpow(2, x * LL(x - 1) / 2 % (P - 1)); } int main() { fac[0] = fac[1] = ifac[0] = ifac[1] = 1; for (int i = 2; i < N; ++i) fac[i] = LL(fac[i - 1]) * i % P; ifac[N - 1] = qpow(fac[N - 1]); for (int i = N - 2; i > 1; --i) ifac[i] = LL(i + 1) * ifac[i + 1] % P; for (int i = 0; i < L; ++i) a[i] = LL(ifac[i]) * qpow(calc(i)) % P; Poly::pow2(a, h, L); for (int i = 0; i < L; ++i) h[i] = LL(h[i]) * calc(i) % P; Poly::sqrt(h, g, L); for (int i = 1; i < L; ++i) printf("%lld\n", LL(g[i]) * fac[i] % P); return 0; }
|