#line 2 "/Users/noya2/Desktop/Noya2_library/template/template.hpp" using namespace std; #include #line 1 "/Users/noya2/Desktop/Noya2_library/template/inout_old.hpp" namespace noya2 { template ostream &operator<<(ostream &os, const pair &p){ os << p.first << " " << p.second; return os; } template istream &operator>>(istream &is, pair &p){ is >> p.first >> p.second; return is; } template ostream &operator<<(ostream &os, const vector &v){ int s = (int)v.size(); for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i]; return os; } template istream &operator>>(istream &is, vector &v){ for (auto &x : v) is >> x; return is; } void in() {} template void in(T &t, U &...u){ cin >> t; in(u...); } void out() { cout << "\n"; } template void out(const T &t, const U &...u){ cout << t; if (sizeof...(u)) cout << sep; out(u...); } template void out(const vector> &vv){ int s = (int)vv.size(); for (int i = 0; i < s; i++) out(vv[i]); } struct IoSetup { IoSetup(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7); } } iosetup_noya2; } // namespace noya2 #line 1 "/Users/noya2/Desktop/Noya2_library/template/const.hpp" namespace noya2{ const int iinf = 1'000'000'007; const long long linf = 2'000'000'000'000'000'000LL; const long long mod998 = 998244353; const long long mod107 = 1000000007; const long double pi = 3.14159265358979323; const vector dx = {0,1,0,-1,1,1,-1,-1}; const vector dy = {1,0,-1,0,1,-1,-1,1}; const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string alp = "abcdefghijklmnopqrstuvwxyz"; const string NUM = "0123456789"; void yes(){ cout << "Yes\n"; } void no(){ cout << "No\n"; } void YES(){ cout << "YES\n"; } void NO(){ cout << "NO\n"; } void yn(bool t){ t ? yes() : no(); } void YN(bool t){ t ? YES() : NO(); } } // namespace noya2 #line 2 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp" #line 6 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp" namespace noya2{ unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){ if (a == 0 || b == 0) return a + b; int n = __builtin_ctzll(a); a >>= n; int m = __builtin_ctzll(b); b >>= m; while (a != b) { int mm = __builtin_ctzll(a - b); bool f = a > b; unsigned long long c = f ? a : b; b = f ? b : a; a = (c - b) >> mm; } return a << std::min(n, m); } template T gcd_fast(T a, T b){ return static_cast(inner_binary_gcd(std::abs(a),std::abs(b))); } long long sqrt_fast(long long n) { if (n <= 0) return 0; long long x = sqrt(n); while ((x + 1) * (x + 1) <= n) x++; while (x * x > n) x--; return x; } template T floor_div(const T n, const T d) { assert(d != 0); return n / d - static_cast((n ^ d) < 0 && n % d != 0); } template T ceil_div(const T n, const T d) { assert(d != 0); return n / d + static_cast((n ^ d) >= 0 && n % d != 0); } template void uniq(std::vector &v){ std::sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); } template inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; } template inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; } template inline bool range(T l, T x, T r){ return l <= x && x < r; } } // namespace noya2 #line 8 "/Users/noya2/Desktop/Noya2_library/template/template.hpp" #define rep(i,n) for (int i = 0; i < (int)(n); i++) #define repp(i,m,n) for (int i = (m); i < (int)(n); i++) #define reb(i,n) for (int i = (int)(n-1); i >= 0; i--) #define all(v) (v).begin(),(v).end() using ll = long long; using ld = long double; using uint = unsigned int; using ull = unsigned long long; using pii = pair; using pll = pair; using pil = pair; using pli = pair; namespace noya2{ /* ~ (. _________ . /) */ } using namespace noya2; #line 2 "c.cpp" #line 2 "/Users/noya2/Desktop/Noya2_library/utility/modint.hpp" #line 4 "/Users/noya2/Desktop/Noya2_library/utility/modint.hpp" #line 2 "/Users/noya2/Desktop/Noya2_library/math/prime.hpp" #line 4 "/Users/noya2/Desktop/Noya2_library/math/prime.hpp" namespace noya2 { constexpr long long safe_mod(long long x, long long m) { x %= m; if (x < 0) x += m; return x; } constexpr long long pow_mod_constexpr(long long x, long long n, int m) { if (m == 1) return 0; unsigned int _m = (unsigned int)(m); unsigned long long r = 1; unsigned long long y = safe_mod(x, m); while (n) { if (n & 1) r = (r * y) % _m; y = (y * y) % _m; n >>= 1; } return r; } constexpr bool is_prime_constexpr(int n) { if (n <= 1) return false; if (n == 2 || n == 7 || n == 61) return true; if (n % 2 == 0) return false; long long d = n - 1; while (d % 2 == 0) d /= 2; constexpr long long bases[3] = {2, 7, 61}; for (long long a : bases) { long long t = d; long long y = pow_mod_constexpr(a, t, n); while (t != n - 1 && y != 1 && y != n - 1) { y = y * y % n; t <<= 1; } if (y != n - 1 && t % 2 == 0) { return false; } } return true; } template constexpr bool is_prime_flag = is_prime_constexpr(n); constexpr std::pair inv_gcd(long long a, long long b) { a = safe_mod(a, b); if (a == 0) return {b, 0}; long long s = b, t = a; long long m0 = 0, m1 = 1; while (t) { long long u = s / t; s -= t * u; m0 -= m1 * u; auto tmp = s; s = t; t = tmp; tmp = m0; m0 = m1; m1 = tmp; } if (m0 < 0) m0 += b / s; return {s, m0}; } constexpr int primitive_root_constexpr(int m) { if (m == 2) return 1; if (m == 167772161) return 3; if (m == 469762049) return 3; if (m == 754974721) return 11; if (m == 998244353) return 3; int divs[20] = {}; divs[0] = 2; int cnt = 1; int x = (m - 1) / 2; while (x % 2 == 0) x /= 2; for (int i = 3; (long long)(i)*i <= x; i += 2) { if (x % i == 0) { divs[cnt++] = i; while (x % i == 0) { x /= i; } } } if (x > 1) { divs[cnt++] = x; } for (int g = 2;; g++) { bool ok = true; for (int i = 0; i < cnt; i++) { if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) { ok = false; break; } } if (ok) return g; } } template constexpr int primitive_root_flag = primitive_root_constexpr(m); // constexpr long long primitive_root_constexpr(long long m){ // if (m == (1LL << 47) - (1LL << 24) + 1) return 3; // return primitive_root_constexpr(static_cast(m)); // } } // namespace noya2 #line 6 "/Users/noya2/Desktop/Noya2_library/utility/modint.hpp" namespace noya2{ struct barrett { unsigned int _m; unsigned long long im; explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {} unsigned int umod() const { return _m; } unsigned int mul(unsigned int a, unsigned int b) const { unsigned long long z = a; z *= b; unsigned long long x = (unsigned long long)((__uint128_t(z) * im) >> 64); unsigned int v = (unsigned int)(z - x * _m); if (_m <= v) v += _m; return v; } }; template struct static_modint { using mint = static_modint; public: static constexpr int mod() { return m; } static mint raw(int v) { mint x; x._v = v; return x; } constexpr static_modint() : _v(0) {} template constexpr static_modint(T v){ long long x = (long long)(v % (long long)(umod())); if (x < 0) x += umod(); _v = (unsigned int)(x); } template constexpr static_modint(T v){ _v = (unsigned int)(v % umod()); } constexpr unsigned int val() const { return _v; } mint& operator++() { _v++; if (_v == umod()) _v = 0; return *this; } mint& operator--() { if (_v == 0) _v = umod(); _v--; return *this; } mint operator++(int) { mint result = *this; ++*this; return result; } mint operator--(int) { mint result = *this; --*this; return result; } constexpr mint& operator+=(const mint& rhs) { _v += rhs._v; if (_v >= umod()) _v -= umod(); return *this; } constexpr mint& operator-=(const mint& rhs) { _v -= rhs._v; if (_v >= umod()) _v += umod(); return *this; } constexpr mint& operator*=(const mint& rhs) { unsigned long long z = _v; z *= rhs._v; _v = (uint)(z % umod()); return *this; } constexpr mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } constexpr mint operator+() const { return *this; } constexpr mint operator-() const { return mint() - *this; } constexpr mint pow(long long n) const { assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } constexpr mint inv() const { if (prime) { assert(_v); return pow(umod() - 2); } else { auto eg = inv_gcd(_v, m); assert(eg.first == 1); return eg.second; } } friend constexpr mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; } friend constexpr mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; } friend constexpr mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; } friend constexpr mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; } friend constexpr bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; } friend constexpr bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; } friend std::ostream &operator<<(std::ostream &os, const mint& p) { return os << p.val(); } friend std::istream &operator>>(std::istream &is, mint &a) { long long t; is >> t; a = mint(t); return (is); } private: unsigned int _v; static constexpr unsigned int umod() { return m; } static constexpr bool prime = is_prime_flag; }; template struct dynamic_modint { using mint = dynamic_modint; public: static int mod() { return (int)(bt.umod()); } static void set_mod(int m) { assert(1 <= m); bt = barrett(m); } static mint raw(int v) { mint x; x._v = v; return x; } dynamic_modint() : _v(0) {} template dynamic_modint(T v){ long long x = (long long)(v % (long long)(umod())); if (x < 0) x += umod(); _v = (unsigned int)(x); } template dynamic_modint(T v){ _v = (unsigned int)(v % umod()); } uint val() const { return _v; } mint& operator++() { _v++; if (_v == umod()) _v = 0; return *this; } mint& operator--() { if (_v == 0) _v = umod(); _v--; return *this; } mint operator++(int) { mint result = *this; ++*this; return result; } mint operator--(int) { mint result = *this; --*this; return result; } mint& operator+=(const mint& rhs) { _v += rhs._v; if (_v >= umod()) _v -= umod(); return *this; } mint& operator-=(const mint& rhs) { _v += mod() - rhs._v; if (_v >= umod()) _v -= umod(); return *this; } mint& operator*=(const mint& rhs) { _v = bt.mul(_v, rhs._v); return *this; } mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } mint operator+() const { return *this; } mint operator-() const { return mint() - *this; } mint pow(long long n) const { assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv() const { auto eg = noya2::inv_gcd(_v, mod()); assert(eg.first == 1); return eg.second; } friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; } friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; } friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; } friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; } friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; } friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; } friend std::ostream &operator<<(std::ostream &os, const mint& p) { return os << p.val(); } friend std::istream &operator>>(std::istream &is, mint &a) { long long t; is >> t; a = mint(t); return (is); } private: unsigned int _v; static barrett bt; static unsigned int umod() { return bt.umod(); } }; template noya2::barrett dynamic_modint::bt(998244353); using modint998244353 = static_modint<998244353>; using modint1000000007 = static_modint<1000000007>; using modint = dynamic_modint<-1>; template concept Modint = requires (T &a){ T::mod(); a.inv(); a.val(); a.pow(declval()); }; } // namespace noya2 #line 4 "c.cpp" using mint = modint998244353; #line 2 "/Users/noya2/Desktop/Noya2_library/math/sieve.hpp" #line 4 "/Users/noya2/Desktop/Noya2_library/math/sieve.hpp" namespace noya2{ struct Sieve { vector primes, factor, mu; Sieve (int N = 1024){ build(N); } void request(int N){ int len = n_max(); if (len >= N) return ; while (len < N) len <<= 1; build(len); } int n_max(){ return factor.size()-1; } private: void build (int N){ primes.clear(); factor.resize(N+1); fill(factor.begin(),factor.end(),0); mu.resize(N+1); fill(mu.begin(),mu.end(),1); for(int n = 2; n <= N; n++) { if (factor[n] == 0){ primes.push_back(n); factor[n] = n; mu[n] = -1; } for (int p : primes){ if(n * p > N || p > factor[n]) break; factor[n * p] = p; mu[n * p] = p == factor[n] ? 0 : -mu[n]; } } } } sieve; int mobius_sieve(int n){ assert(1 <= n && n <= sieve.n_max()); return sieve.mu[n]; } bool is_prime_sieve(int n){ if (n <= 2) return n == 2; assert(n <= sieve.n_max()); return sieve.factor[n] == n; } vector> prime_factorization_sieve(int n){ assert(1 <= n && n <= sieve.n_max()); vector facts; while (n > 1){ int p = sieve.factor[n]; facts.push_back(p); n /= p; } vector> pes; int siz = facts.size(); for (int l = 0, r = 0; l < siz; l = r){ while (r < siz && facts[r] == facts[l]) r++; pes.emplace_back(facts[l],r-l); } return pes; } vector divisor_enumeration_sieve(int n){ auto pes = prime_factorization_sieve(n); vector divs = {1}; for (auto [p, e] : pes){ vector nxt; nxt.reserve(divs.size() * (e+1)); for (auto x : divs){ for (int tt = 0; tt <= e; tt++){ nxt.push_back(x); x *= p; } } swap(divs,nxt); } return divs; } } // namespace noya2 #line 6 "c.cpp" const int mx = 200010; const int sq = sqrt(mx); template struct mulinv_group { using value_type = pair; static constexpr value_type op(const value_type &a, const value_type &b){ return value_type(a.first*b.first,a.second*b.second); } static constexpr value_type e(){ return value_type(T(1),T(1)); } static constexpr value_type inv(const value_type &a){ return value_type(a.second,a.first); } }; template struct Monoid_Max { using X = E; using value_type = X; static constexpr X op(const X &x, const X &y) noexcept { return max(x, y); } static constexpr X unit() { return E(0); } static constexpr bool commute = true; }; namespace maspy { using pi = pair; using vi = vector; template using vc = vector; template using vvc = vector>; template using vvvc = vector>; template using vvvvc = vector>; template using vvvvvc = vector>; template using pq = priority_queue; template using pqg = priority_queue, greater>; // https://trap.jp/post/1224/ #define FOR1(a) for (ll _ = 0; _ < ll(a); ++_) #define FOR2(i, a) for (ll i = 0; i < ll(a); ++i) #define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i) #define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c)) #define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i) #define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i) #define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i) #define overload4(a, b, c, d, e, ...) e #define overload3(a, b, c, d, ...) d #define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__) #define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__) #define len(x) ll(x.size()) // (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2) int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); } int topbit(uint32_t x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); } int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); } int topbit(uint64_t x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); } // 冪等なモノイドであることを仮定。disjoint sparse table より x 倍高速 template struct Sparse_Table { using MX = Monoid; using X = typename MX::value_type; int n, log; vvc dat; Sparse_Table() {} Sparse_Table(int n) { build(n); } template Sparse_Table(int n, F f) { build(n, f); } Sparse_Table(const vc& v) { build(v); } void build(int m) { build(m, [](int i) -> X { return MX::unit(); }); } void build(const vc& v) { build(len(v), [&](int i) -> X { return v[i]; }); } template void build(int m, F f) { n = m, log = 1; while ((1 << log) < n) ++log; dat.resize(log); dat[0].resize(n); FOR(i, n) dat[0][i] = f(i); FOR(i, log - 1) { dat[i + 1].resize(len(dat[i]) - (1 << i)); FOR(j, len(dat[i]) - (1 << i)) { dat[i + 1][j] = MX::op(dat[i][j], dat[i][j + (1 << i)]); } } } X prod(int L, int R) { if (L == R) return MX::unit(); if (R == L + 1) return dat[0][L]; int k = topbit(R - L - 1); return MX::op(dat[k][L], dat[k][R - (1 << k)]); } template int max_right(const F check, int L) { assert(0 <= L && L <= n && check(MX::unit())); if (L == n) return n; int ok = L, ng = n + 1; while (ok + 1 < ng) { int k = (ok + ng) / 2; bool bl = check(prod(L, k)); if (bl) ok = k; if (!bl) ng = k; } return ok; } template int min_left(const F check, int R) { assert(0 <= R && R <= n && check(MX::unit())); if (R == 0) return 0; int ok = R, ng = -1; while (ng + 1 < ok) { int k = (ok + ng) / 2; bool bl = check(prod(k, R)); if (bl) ok = k; if (!bl) ng = k; } return ok; } }; template struct Static_Range_Product { using MX = Monoid; using X = typename MX::value_type; int N, b_num; vc A, pre, suf; // inclusive SPARSE_TABLE ST; Static_Range_Product() {} template Static_Range_Product(int n, F f) { build(n, f); } Static_Range_Product(const vc& v) { build(v); } void build(const vc& v) { build(len(v), [&](int i) -> X { return v[i]; }); } template void build(int m, F f) { N = m; b_num = N >> LOG; A.resize(N); FOR(i, N) A[i] = f(i); pre = A, suf = A; constexpr int mask = (1 << LOG) - 1; FOR(i, 1, N) { if (i & mask) pre[i] = MX::op(pre[i - 1], A[i]); } FOR_R(i, 1, N) { if (i & mask) suf[i - 1] = MX::op(A[i - 1], suf[i]); } ST.build(b_num, [&](int i) -> X { return suf[i << LOG]; }); } // O(1) or O(R-L) X prod(int L, int R) { if (L == R) return MX::unit(); R -= 1; int a = L >> LOG, b = R >> LOG; if (a < b) { X x = ST.prod(a + 1, b); x = MX::op(suf[L], x); x = MX::op(x, pre[R]); return x; } X x = A[L]; FOR(i, L + 1, R + 1) x = MX::op(x, A[i]); return x; } }; } // namespace maspy #line 2 "/Users/noya2/Desktop/Noya2_library/misc/concepts.hpp" #include namespace noya2 { template concept Monoid = requires { typename monoid::value_type; {monoid::op(declval(),declval())} -> std::same_as; {monoid::e()} -> std::same_as; }; template concept Group = requires { requires Monoid; {group::inv(declval())} -> std::same_as; }; } // namespace noya2 #line 2 "/Users/noya2/Desktop/Noya2_library/data_structure/compress.hpp" #line 5 "/Users/noya2/Desktop/Noya2_library/data_structure/compress.hpp" namespace noya2{ template struct compress { std::vector raws; compress () {} compress (const vector &_raws) : raws(_raws){ build(); } void build(){ std::sort(raws.begin(), raws.end()); raws.erase(std::unique(raws.begin(), raws.end()), raws.end()); } int id(const T &raw){ return lb(raw); } T raw(const int &id){ return raws[id]; } void add(const T &raw){ raws.emplace_back(raw); } void reserve(size_t sz){ raws.reserve(sz); } size_t size(){ return raws.size(); } int lb(const T &raw){ return lower_bound(all(raws),raw) - raws.begin(); } int ub(const T &raw){ return upper_bound(all(raws),raw) - raws.begin(); } bool contains(const T &raw){ int jd = lb(raw); if (jd < (int)size()) return raws[jd] == raw; return false; } int contains_id(const T &raw){ int jd = lb(raw); if (jd < (int)size() && raws[jd] == raw) return jd; return -1; } }; } // namespace noya2 #line 204 "c.cpp" template struct static_online_rectangle_sum { using T = G::value_type; int n, sz; std::vector> cums; std::vector> ys; static_online_rectangle_sum(int _n, const std::vector> &ps) : n(_n){ sz = bit_ceil(n); cums.resize(sz * 2); ys.resize(sz * 2); for (auto [x, y, v] : ps){ int xid = x + sz; ys[xid].add(y); while (xid > 1){ xid >>= 1; ys[xid].add(y); } } for (int i = 1; i < 2*sz; i++){ ys[i].build(); cums[i].resize(ys[i].size()+1, G::e()); } for (auto [x, y, v] : ps){ int xid = x + sz; assert(ys[xid].contains(y)); int yid = ys[xid].id(y) + 1; cums[xid][yid] = G::op(cums[xid][yid], v); while (xid > 1){ xid >>= 1; assert(ys[xid].contains(y)); yid = ys[xid].id(y) + 1; cums[xid][yid] = G::op(cums[xid][yid], v); } } for (int i = 1; i < 2*sz; i++){ for (int j = 0; j < (int)ys[i].size(); j++){ cums[i][j+1] = G::op(cums[i][j], cums[i][j+1]); } } } T inner_prod(int xid, int lq, int rq){ return G::op(G::inv(cums[xid][ys[xid].lb(lq)]),cums[xid][ys[xid].lb(rq)]); } T prod(int li, int ri, int lq, int rq){ T ret = G::e(); for (li += sz, ri += sz; li < ri; li >>= 1, ri >>= 1){ if (li & 1) ret = G::op(ret, inner_prod(li, lq, rq)), li++; if (ri & 1) --ri, ret = G::op(ret, inner_prod(ri, lq, rq)); } return ret; } }; void solve(){ int n; in(n); vector a(n); in(a); vector> ids(mx); vector psml; vector pid(mx); for (int p : sieve.primes){ if (p >= sq) break; pid[p] = psml.size(); psml.emplace_back(p); } int sz = psml.size(); vector> pws(sz,vector(30,1)); rep(i,sz){ rep(j,30-1){ pws[i][j+1] = pws[i][j] * psml[i]; } } using Mono = Monoid_Max; using ST = maspy::Sparse_Table; vector> init(sz,vector(n)); rep(i,n){ for (auto [p, e] : prime_factorization_sieve(a[i])){ if (p < sq){ init[pid[p]][i] = e; } else { assert(e == 1); ids[p].emplace_back(i); } } } mint tot = 1; vector> segs(sz); rep(i,sz){ segs[i] = maspy::Static_Range_Product(init[i]); } using T = mulinv_group::value_type; vector> upds; rep(p,mx){ if (ids[p].empty()) continue; ids[p].emplace_back(n); tot *= p; int pre = -1; mint ip = mint(p).inv(); for (int i : ids[p]){ upds.push_back({pre+1,i+1,T{mint(p),ip}}); pre = i; } } static_online_rectangle_sum> rt(n+2,upds); int q; in(q); mint pans = 1; while (q--){ mint A, B; in(A,B); mint x = A * pans; int y = x.val() % n + 1; mint z = B * pans; int w = z.val() % n + 1; int l = min(y,w), r = max(y,w); l--; // int l, r; in(l,r); l--; mint ans = tot * rt.prod(0,l+1,r+1,n+2).second; rep(i,sz){ ans *= pws[i][segs[i].prod(l,r)]; } out(ans); pans = ans; } } int main(){ sieve.request(mx); int t = 1; //in(t); while (t--) { solve(); } }