int n; int a[kMaxN], res[kMaxN], fac[kMaxN], ifac[kMaxN];
constexprintqpow(int bs, int64_t idx = kMod - 2){ int ret = 1; for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod) if (idx & 1) ret = (int64_t)ret * bs % kMod; return ret; }
inlineintadd(int x, int y){ return (x + y >= kMod ? x + y - kMod : x + y); } inlineintsub(int x, int y){ return (x >= y ? x - y : x - y + kMod); } inlinevoidinc(int &x, int y){ (x += y) >= kMod ? x -= kMod : x; } inlinevoiddec(int &x, int y){ (x -= y) < 0 ? x += kMod : x; }
voidprework(int n = (kMaxN - 5) / 2){ inited = 1; int c = 0; for (; (1 << c) <= n; ++c) {} c = std::min(c - 1, kB - 2); polyg[0] = 1, polyg[1 << c] = qpow(kG, 1 << (kB - 2 - c)); for (int i = c; i; --i) polyg[1 << i - 1] = (int64_t)polyg[1 << i] * polyg[1 << i] % kMod; for (int i = 1; i < (1 << c); ++i) polyg[i] = (int64_t)polyg[i & (i - 1)] * polyg[i & -i] % kMod; }
intgetlen(int n){ int len = 1; for (; len <= n; len <<= 1) {} return len; }
structPoly : std::vector<int> { using vector::vector; using vector::operator [];
friend Poly operator -(Poly a) { static Poly c; c.resize(a.size()); for (int i = 0; i < c.size(); ++i) c[i] = sub(0, c[i]); return c; } friend Poly operator +(Poly a, Poly b) { static Poly c; c.resize(std::max(a.size(), b.size())); for (int i = 0; i < c.size(); ++i) c[i] = add((i < a.size() ? a[i] : 0), (i < b.size() ? b[i] : 0)); return c; } friend Poly operator -(Poly a, Poly b) { static Poly c; c.resize(std::max(a.size(), b.size())); for (int i = 0; i < c.size(); ++i) c[i] = sub((i < a.size() ? a[i] : 0), (i < b.size() ? b[i] : 0)); return c; } friendvoiddif(Poly &a, int len){ if (a.size() < len) a.resize(len); for (int l = len; l != 1; l >>= 1) { int m = l / 2; for (int i = 0, k = 0; i < len; i += l, ++k) { for (int j = 0; j < m; ++j) { int tmp = (int64_t)a[i + j + m] * polyg[k] % kMod; a[i + j + m] = sub(a[i + j], tmp); inc(a[i + j], tmp); } } } } friendvoiddit(Poly &a, int len){ if (a.size() < len) a.resize(len); for (int l = 2; l <= len; l <<= 1) { int m = l / 2; for (int i = 0, k = 0; i < len; i += l, ++k) { for (int j = 0; j < m; ++j) { int tmp = a[i + j + m]; a[i + j + m] = (int64_t)sub(a[i + j], tmp) * polyg[k] % kMod; inc(a[i + j], tmp); } } } int invl = qpow(len); for (int i = 0; i < len; ++i) a[i] = (int64_t)a[i] * invl % kMod; std::reverse(a.begin() + 1, a.begin() + len); } friend Poly operator *(Poly a, Poly b) { if (!inited) prework(); int n = a.size() + b.size() - 1, len = getlen(n); a.resize(len), b.resize(len); dif(a, len), dif(b, len); for (int i = 0; i < len; ++i) a[i] = (int64_t)a[i] * b[i] % kMod; dit(a, len); a.resize(n); return a; } friend Poly operator *(Poly a, int b) { static Poly c; c = a; for (auto &x : c) x = (int64_t)x * b % kMod; return c; } friend Poly operator *(int a, Poly b) { static Poly c; c = b; for (auto &x : c) x = (int64_t)x * a % kMod; return c; } friendvoidoperator *=(Poly &a, Poly b) { if (!inited) prework(); int n = a.size() + b.size() - 1, len = getlen(n); a.resize(len), b.resize(len); dif(a, len), dif(b, len); for (int i = 0; i < len; ++i) a[i] = (int64_t)a[i] * b[i] % kMod; dit(a, len); a.resize(n); } friend Poly shift(Poly f, int d){ if (d == 0) return f; if ((int)f.size() + d < 0) return {}; Poly g((int)f.size() + d, 0); for (int i = 0; i < g.size(); ++i) if (i - d >= 0 && i - d < f.size()) g[i] = f[i - d]; return g; } }; } // namespace POLY
using POLY::Poly;
intC(int m, int n){ if (m < n || m < 0 || n < 0) return0; return1ll * fac[m] * ifac[n] % kMod * ifac[m - n] % kMod; }
voidprework(int n = 5e5){ fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = 1ll * i * fac[i - 1] % kMod; ifac[n] = qpow(fac[n]); for (int i = n; i; --i) ifac[i - 1] = 1ll * i * ifac[i] % kMod; }
Poly solve(int l, int r, Poly F){ assert(F.size() == a[r] - a[l - 1] + 1); if (l == r) { int ret = 0; for (auto x : F) inc(ret, x); return {ret}; } int mid = (l + r) >> 1, llen = mid - l + 1, rlen = r - mid, d = a[mid] - a[l - 1]; Poly f = solve(mid + 1, r, shift(F, -d)); Poly G(d + 1, 0); G[d] = f[0]; Poly pf(rlen, 0), pg(d + rlen - 1, 0); for (int i = 0; i <= rlen - 1; ++i) pf[i] = 1ll * f[rlen - 1 - i] * ifac[rlen - 1 - i] % kMod; for (int i = 0; i <= d + rlen - 2; ++i) pg[i] = fac[i]; pf *= pg; for (int i = 0; i <= d - 1; ++i) if (d + rlen - 2 - i >= 0 && d + rlen - 2 - i < pf.size()) inc(G[i], 1ll * pf[d + rlen - 2 - i] * ifac[d - 1 - i] % kMod); // if (d) { pf.clear(), pg.clear(); pf.resize(d, 0), pg.resize(d, 0); for (int i = 0; i < d; ++i) pf[i] = F[d - 1 - i]; for (int i = 0; i < d; ++i) pg[i] = 1ll * fac[i + rlen - 1] * ifac[i] % kMod; pf *= pg; for (int i = 0; i <= d - 1; ++i) inc(G[i], 1ll * pf[d - 1 - i] * ifac[rlen - 1] % kMod); } Poly ff = f; if (d) { pf.clear(), pg.clear(); pf.resize(rlen, 0), pg.resize(rlen, 0); for (int i = 0; i < rlen; ++i) pf[i] = f[rlen - 1 - i]; for (int i = 1; i < rlen; ++i) pg[i] = 1ll * fac[d - 1 + i] * ifac[i] % kMod; pf *= pg; for (int i = 0; i <= rlen - 1; ++i) inc(ff[i], 1ll * pf[rlen - 1 - i] * ifac[d - 1] % kMod); } if (d) { pf.clear(), pg.clear(); pf.resize(d, 0), pg.resize(d + rlen - 1, 0); for (int i = 0; i < d; ++i) pf[i] = 1ll * F[d - 1 - i] * ifac[d - 1 - i] % kMod; for (int i = 0; i < d + rlen - 1; ++i) pg[i] = fac[i]; pf *= pg; for (int i = 0; i <= rlen - 1; ++i) if (d + rlen - 2 - i >= 0 && d + rlen - 2 - i < pf.size()) inc(ff[i], 1ll * pf[d + rlen - 2 - i] * ifac[rlen - 1 - i] % kMod); } assert(ff.size() == r - mid); Poly g = solve(l, mid, G); return g + shift(ff, g.size()); }
voiddickdreamer(){ std::cin >> n; prework(); for (int i = 1; i <= n; ++i) std::cin >> a[i], --a[i]; auto res = solve(1, n, Poly(a[n] + 1, 1)); res.emplace_back(1); for (auto x : res) std::cout << x << ' '; }