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
| #include <cstdio> #include <vector> using LL = long long; using poly = std::vector<int>; const int N = 1.6e5 + 100, P = 998244353, G = 3, iG = 332748118; int n, m, f[N]; int rev[1 << 20 | 100]; int ifac[N], miv[N << 1], mfac[N << 1], imfac[N << 1]; 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; } void init() { int fac = 1; for (int i = 2; i <= n; ++i) fac = LL(i) * fac % P; ifac[n] = qpow(fac); for (int i = n - 1; i > 1; --i) ifac[i] = LL(i + 1) * ifac[i + 1] % P; ifac[0] = ifac[1] = 1; mfac[0] = m - n; for (int i = 1; i <= (n << 1); ++i) mfac[i] = LL(m - n + i) * mfac[i - 1] % P; imfac[n << 1] = qpow(mfac[n << 1]); for (int i = (n << 1) - 1; ~i; --i) imfac[i] = LL(m - n + i + 1) * imfac[i + 1] % P; miv[0] = imfac[0]; for (int i = 1; i <= (n << 1); ++i) miv[i] = LL(imfac[i]) * mfac[i - 1] % P; } void rdy(int &bit, int &tot, int len){ for (tot = 1, bit = 0; tot <= len; tot <<= 1, ++bit); } void get_r(int bit, int tot){ for (int i = 1; i < tot; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1)); } void ntt(int *x, int tot, int op) { static int gn[1 << 20 | 100]; for (int i = 1; i < tot; ++i) if (i < rev[i]) std::swap(x[i], x[rev[i]]); for (int mid = 1; mid < tot; mid <<= 1) { int g0 = qpow(op == 1 ? G : iG, (P - 1) / (mid << 1)); gn[0] = 1; for (int i = 1; i < mid; ++i) gn[i] = LL(g0) * gn[i - 1] % 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(t) * x[i] % P; } poly operator * (poly x, poly y) { if (x.empty() || y.empty()) return {}; int n = x.size(), m = y.size(), tot, bit; rdy(bit, tot, n + m), get_r(bit, tot); x.resize(tot), y.resize(tot); ntt(x.data(), tot, 1); if (x == y) y = x; else ntt(y.data(), tot, 1); for (int i = 0; i < tot; ++i) x[i] = LL(x[i]) * y[i] % P; ntt(x.data(), tot, -1); return x.resize(n + m - 1), x; } int main() { scanf("%d %d", &n, &m); for (int i = 0; i <= n; ++i) scanf("%d", f + i), f[i] %= P; init(); poly g(n + 1), h(2 * n + 1); for (int i = 0; i <= n; ++i) { g[i] = LL(f[i]) * ifac[i] % P * ifac[n - i] % P; if ((n - i) & 1) g[i] = P - g[i]; } for (int i = 0; i <= (n << 1); ++i) h[i] = miv[i]; poly l = g * h; printf("%d ", LL(mfac[n]) * l[n] % P); for (int i = 1; i <= n; ++i) printf("%d ", LL(mfac[i + n]) * imfac[i - 1] % P * l[i + n] % P); return 0; }
|