#line 1 "a.cpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* macro */ #define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++) #define rrep(i, a, n) for (int i = ((int)(n)-1); i >= (int)(a); i--) #define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++) #define RRep(i, a, n) for (i64 i = ((i64)(n)-i64(1)); i >= (i64)(a); i--) #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() /* macro end */ /* template */ namespace ebi { #ifdef LOCAL #define debug(...) \ std::cerr << "LINE: " << __LINE__ << " [" << #__VA_ARGS__ << "]:", \ debug_out(__VA_ARGS__) #else #define debug(...) #endif void debug_out() { std::cerr << std::endl; } template void debug_out(Head h, Tail... t) { std::cerr << " " << h; if (sizeof...(t) > 0) std::cerr << " :"; debug_out(t...); } template std::ostream &operator<<(std::ostream &os, const std::pair &pa) { return os << pa.first << " " << pa.second; } template std::istream &operator>>(std::istream &os, std::pair &pa) { return os >> pa.first >> pa.second; } template std::ostream &operator<<(std::ostream &os, const std::vector &vec) { for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os; } template std::istream &operator>>(std::istream &os, std::vector &vec) { for (T &e : vec) std::cin >> e; return os; } template std::ostream &operator<<(std::ostream &os, const std::optional &opt) { if (opt) { os << opt.value(); } else { os << "invalid value"; } return os; } using std::size_t; using i32 = std::int32_t; using u32 = std::uint32_t; using i64 = std::int64_t; using u64 = std::uint64_t; using i128 = __int128_t; using u128 = __uint128_t; template inline bool chmin(T &a, T b) { if (a > b) { a = b; return true; } return false; } template inline bool chmax(T &a, T b) { if (a < b) { a = b; return true; } return false; } template T pow(T x, i64 n) { T res = 1; while (n > 0) { if (n & 1) res = res * x; x = x * x; n >>= 1; } return res; } template struct Edge { int to; T cost; Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {} }; template struct Graph : std::vector>> { using std::vector>>::vector; void add_edge(int u, int v, T w, bool directed = false) { (*this)[u].emplace_back(v, w); if (directed) return; (*this)[v].emplace_back(u, w); } }; struct graph : std::vector> { using std::vector>::vector; void add_edge(int u, int v, bool directed = false) { (*this)[u].emplace_back(v); if (directed) return; (*this)[v].emplace_back(u); } }; constexpr i64 LNF = std::numeric_limits::max() / 4; constexpr int INF = std::numeric_limits::max() / 2; const std::vector dy = {1, 0, -1, 0, 1, 1, -1, -1}; const std::vector dx = {0, 1, 0, -1, 1, -1, 1, -1}; } // namespace ebi #line 2 "fps/fps.hpp" #line 7 "fps/fps.hpp" namespace ebi { template (*convolution)( const std::vector &, const std::vector &)> struct FormalPowerSeries : std::vector { private: using std::vector::vector; using std::vector::vector::operator=; using FPS = FormalPowerSeries; public: FPS operator+(const FPS &rhs) const noexcept { return FPS(*this) += rhs; } FPS operator-(const FPS &rhs) const noexcept { return FPS(*this) -= rhs; } FPS operator*(const FPS &rhs) const noexcept { return FPS(*this) *= rhs; } FPS operator/(const FPS &rhs) const noexcept { return FPS(*this) /= rhs; } FPS operator%(const FPS &rhs) const noexcept { return FPS(*this) %= rhs; } FPS operator+(const mint &rhs) const noexcept { return FPS(*this) += rhs; } FPS operator-(const mint &rhs) const noexcept { return FPS(*this) -= rhs; } FPS operator*(const mint &rhs) const noexcept { return FPS(*this) *= rhs; } FPS operator/(const mint &rhs) const noexcept { return FPS(*this) /= rhs; } FPS &operator+=(const FPS &rhs) noexcept { if (this->size() < rhs.size()) this->resize(rhs.size()); for (int i = 0; i < (int)rhs.size(); ++i) { (*this)[i] += rhs[i]; } return *this; } FPS &operator-=(const FPS &rhs) noexcept { if (this->size() < rhs.size()) this->resize(rhs.size()); for (int i = 0; i < (int)rhs.size(); ++i) { (*this)[i] -= rhs[i]; } return *this; } FPS &operator*=(const FPS &rhs) noexcept { *this = convolution(*this, rhs); return *this; } FPS &operator/=(const FPS &rhs) noexcept { int n = deg() - 1; int m = rhs.deg() - 1; if (n < m) { *this = {}; return *this; } *this = (*this).rev() * rhs.rev().inv(n - m + 1); (*this).resize(n - m + 1); std::reverse((*this).begin(), (*this).end()); return *this; } FPS &operator%=(const FPS &rhs) noexcept { *this -= *this / rhs * rhs; shrink(); return *this; } FPS &operator+=(const mint &rhs) noexcept { if (this->empty()) this->resize(1); (*this)[0] += rhs; return *this; } FPS &operator-=(const mint &rhs) noexcept { if (this->empty()) this->resize(1); (*this)[0] -= rhs; return *this; } FPS &operator*=(const mint &rhs) noexcept { for (int i = 0; i < deg(); ++i) { (*this)[i] *= rhs; } return *this; } FPS &operator/=(const mint &rhs) noexcept { mint inv_rhs = rhs.inv(); for (int i = 0; i < deg(); ++i) { (*this)[i] *= inv_rhs; } return *this; } FPS operator>>(int d) const { if (deg() <= d) return {}; FPS f = *this; f.erase(f.begin(), f.begin() + d); return f; } FPS operator<<(int d) const { FPS f = *this; f.insert(f.begin(), d, 0); return f; } FPS operator-() const { FPS g(this->size()); for (int i = 0; i < (int)this->size(); i++) g[i] = -(*this)[i]; return g; } FPS pre(int sz) const { return FPS(this->begin(), this->begin() + std::min(deg(), sz)); } FPS rev() const { auto f = *this; std::reverse(f.begin(), f.end()); return f; } FPS differential() const { int n = deg(); FPS g(std::max(0, n - 1)); for (int i = 0; i < n - 1; i++) { g[i] = (*this)[i + 1] * (i + 1); } return g; } FPS integral() const { int n = deg(); FPS g(n + 1); g[0] = 0; if (n > 0) g[1] = 1; auto mod = mint::mod(); for (int i = 2; i <= n; i++) g[i] = (-g[mod % i]) * (mod / i); for (int i = 0; i < n; i++) g[i + 1] *= (*this)[i]; return g; } FPS inv(int d = -1) const { int n = 1; if (d < 0) d = deg(); FPS g(n); g[0] = (*this)[0].inv(); while (n < d) { n <<= 1; g = (g * 2 - g * g * this->pre(n)).pre(n); } g.resize(d); return g; } FPS log(int d = -1) const { assert((*this)[0].val() == 1); if (d < 0) d = deg(); return ((*this).differential() * (*this).inv(d)).pre(d - 1).integral(); } FPS exp(int d = -1) const { assert((*this)[0].val() == 0); int n = 1; if (d < 0) d = deg(); FPS g(n); g[0] = 1; while (n < d) { n <<= 1; g = (g * (this->pre(n) - g.log(n) + 1)).pre(n); } g.resize(d); return g; } FPS pow(int64_t k, int d = -1) const { const int n = deg(); if (d < 0) d = n; if (k == 0) { FPS f(d); if (d > 0) f[0] = 1; return f; } for (int i = 0; i < n; i++) { if ((*this)[i] != 0) { mint rev = (*this)[i].inv(); FPS f = (((*this * rev) >> i).log(d) * k).exp(d); f *= (*this)[i].pow(k); f = (f << (i * k)).pre(d); if (f.deg() < d) f.resize(d); return f; } if (i + 1 >= (d + k - 1) / k) break; } return FPS(d); } int deg() const { return (*this).size(); } void shrink() { while ((!this->empty()) && this->back() == 0) this->pop_back(); } int count_terms() const { int c = 0; for (int i = 0; i < deg(); i++) { if ((*this)[i] != 0) c++; } return c; } std::optional sqrt(int d = -1) const; }; } // namespace ebi #line 2 "fps/fps_sparse.hpp" #line 5 "fps/fps_sparse.hpp" #line 2 "utility/modint_func.hpp" #line 5 "utility/modint_func.hpp" namespace ebi { template mint inv(int n) { static const int mod = mint::mod(); static std::vector dat = {0, 1}; assert(0 <= n); if (n >= mod) n -= mod; while (int(dat.size()) <= n) { int num = dat.size(); int q = (mod + num - 1) / num; dat.emplace_back(dat[num * q - mod] * mint(q)); } return dat[n]; } } // namespace ebi #line 7 "fps/fps_sparse.hpp" namespace ebi { template std::vector mul_sparse(const std::vector &f, const std::vector &g) { int n = f.size(); int m = g.size(); std::vector> cf, cg; for (int i = 0; i < n; i++) { if (f[i] != 0) cf.emplace_back(i, f[i]); } for (int i = 0; i < m; i++) { if (g[i] != 0) cg.emplace_back(i, g[i]); } std::vector h(n + m - 1); for (auto [i, p] : cf) { for (auto [j, q] : cg) { h[i + j] += p * q; } } return h; } template std::vector inv_sparse(const std::vector &f, int d = -1) { assert(f[0] != 0); if (d < 0) { d = f.size(); } std::vector> ret; for (int i = 1; i < int(f.size()); i++) { if (f[i] != 0) { ret.emplace_back(i, f[i]); } } std::vector g(d); g[0] = f[0].inv(); for (int i = 1; i < d; i++) { for (auto [k, p] : ret) { if (i - k < 0) break; g[i] -= g[i - k] * p; } g[i] *= g[0]; } return g; } template std::vector exp_sparse(const std::vector &f, int d = -1) { int n = f.size(); if (d < 0) d = n; std::vector> ret; for (int i = 1; i < n; i++) { if (f[i] != 0) { ret.emplace_back(i - 1, f[i] * i); } } std::vector g(d); g[0] = 1; for (int i = 0; i < d - 1; i++) { for (auto [k, p] : ret) { if (i - k < 0) break; g[i + 1] += g[i - k] * p; } g[i + 1] *= inv(i + 1); } return g; } template std::vector log_sparse(const std::vector &f, int d = -1) { int n = f.size(); if (d < 0) d = n; std::vector df(d); for (int i = 0; i < std::min(d, n - 1); i++) { df[i] = f[i + 1] * (i + 1); } auto dg = mul_sparse(df, inv_sparse(f)); dg.resize(d); std::vector g(d); for (int i = 0; i < d - 1; i++) { g[i + 1] = dg[i] * inv(i + 1); } return g; } template std::vector pow_sparse_1(const std::vector &f, long long k, int d = -1) { int n = f.size(); assert(n == 0 || f[0] == 1); std::vector> ret; for (int i = 1; i < n; i++) { if (f[i] != 0) ret.emplace_back(i, f[i]); } std::vector g(d); g[0] = 1; for (int i = 0; i < d - 1; i++) { for (const auto &[j, cf] : ret) { if (i + 1 - j < 0) break; g[i + 1] += (mint(k) * mint(j) - mint(i - j + 1)) * cf * g[i + 1 - j]; } g[i + 1] *= inv(i + 1); } return g; } template std::vector pow_sparse(const std::vector &f, long long k, int d = -1) { int n = f.size(); if (d < 0) d = n; assert(k >= 0); if (k == 0) { std::vector g(d); if (d > 0) g[0] = 1; return g; } for (int i = 0; i < n; i++) { if (f[i] != 0) { mint rev = f[i].inv(); std::vector f2(n - i); for (int j = i; j < n; j++) { f2[j - i] = f[j] * rev; } f2 = pow_sparse_1(f2, k, d); mint fk = f[i].pow(k); std::vector g(d); for (int j = 0; j < int(f2.size()); j++) { if (j + i * k >= d) break; g[j + i * k] = f2[j] * fk; } return g; } if (i >= (d + k - 1) / k) break; } return std::vector(d); } } // namespace ebi #line 167 "a.cpp" #include #include #include namespace ebi { using mint = atcoder::modint998244353; using FPS = FormalPowerSeries; FPS op(FPS lhs, FPS rhs) { return lhs + rhs; } FPS e() { return {0}; } void main_() { int n; std::cin >> n; atcoder::segtree seg(n); rep(i,0,n) { i64 p; std::cin >> p; std::vector f(n+1); f[0] = 1; f[1] = p; f = log_sparse(f, n+1); FPS g(n+1); rep(i,0,n+1) g[i] = f[i]; seg.set(i, g); } int q; std::cin >> q; while(q--) { int a,b,k; std::cin >> a >> b >> k; a--; std::cout << seg.prod(a, b).exp(k + 1)[k].val() << '\n'; } } } // namespace ebi int main() { std::cout << std::fixed << std::setprecision(15); std::cin.tie(nullptr); std::ios::sync_with_stdio(false); int t = 1; // std::cin >> t; while (t--) { ebi::main_(); } return 0; }