1+ /* *
2+ * @file 14140.cpp
3+ * @author Macesuted ([email protected] ) 4+ * @date 2025-10-11
5+ *
6+ * @copyright Copyright (c) 2025
7+ *
8+ */
9+
10+ #include < bits/stdc++.h>
11+ using namespace std ;
12+
13+ #ifndef LOCAL
14+ #define endl ' \n '
15+ #endif
16+
17+ bool mem1;
18+
19+ #define mod 998244353
20+ #define maxn 200005
21+
22+ using pll = pair<int64_t , int64_t >;
23+
24+ int64_t qpow (int64_t a, int64_t x) {
25+ int64_t ans = 1 ;
26+ while (x) {
27+ if (x & 1 ) ans = ans * a % mod;
28+ a = a * a % mod, x >>= 1 ;
29+ }
30+ return ans;
31+ }
32+ int64_t inv (int64_t a) { return qpow (a, mod - 2 ); }
33+
34+ class SegmentTree {
35+ private:
36+ struct Node {
37+ Node *l, *r;
38+ pll val;
39+ Node (void ) { l = r = nullptr , val = {1 , 0 }; }
40+ };
41+
42+ vector<Node *> roots;
43+
44+ pll merge (const pll &a, const pll &b) { return {a.first * b.first % mod, a.second + b.second }; }
45+ void pushUp (Node *p) {
46+ return p->val = (p->l && p->r ) ? merge (p->l ->val , p->r ->val ) : p->l ? p->l ->val : p->r ->val , void ();
47+ }
48+ void insert (Node *&p, int l, int r, int qp) {
49+ p = new Node (p ? *p : Node ());
50+ if (l == r) return p->val = merge (p->val , {qp, qp - 1 }), void ();
51+ int mid = (l + r) >> 1 ;
52+ qp <= mid ? insert (p->l , l, mid, qp) : insert (p->r , mid + 1 , r, qp);
53+ return pushUp (p);
54+ }
55+ pll query (Node *p, int l, int r, int ql, int qr) {
56+ if (!p) return {1 , 0 };
57+ if (ql <= l && r <= qr) return p->val ;
58+ int mid = (l + r) >> 1 ;
59+ if (qr <= mid) return query (p->l , l, mid, ql, qr);
60+ if (ql > mid) return query (p->r , mid + 1 , r, ql, qr);
61+ return merge (query (p->l , l, mid, ql, qr), query (p->r , mid + 1 , r, ql, qr));
62+ }
63+
64+ public:
65+ void build (int n, int a[]) {
66+ roots.resize (n + 1 );
67+ for (int i = 1 ; i <= n; i++) insert (roots[i] = roots[i - 1 ], 1 , mod - 1 , a[i]);
68+ return ;
69+ }
70+ pll query (int l, int r, int vl, int vr) {
71+ pll retl = query (roots[l - 1 ], 1 , mod - 1 , vl, vr), retr = query (roots[r], 1 , mod - 1 , vl, vr);
72+ return {retr.first * inv (retl.first ) % mod, retr.second - retl.second };
73+ }
74+ } SGT;
75+
76+ int a[maxn];
77+
78+ void solve (void ) {
79+ int n, q;
80+ cin >> n >> q;
81+
82+ for (int i = 1 ; i <= n; i++) cin >> a[i];
83+ SGT.build (n, a);
84+
85+ while (q--) {
86+ int l, r;
87+ int64_t k;
88+ cin >> l >> r >> k;
89+
90+ int vl = 0 , vr = mod;
91+ while (vl + 1 < vr) {
92+ int mid = (vl + vr) >> 1 ;
93+ (SGT.query (l, r, 1 , mid).second <= k ? vl : vr) = mid;
94+ }
95+
96+ if (vl == mod - 1 ) {
97+ cout << 1 << endl;
98+ continue ;
99+ }
100+
101+ k -= SGT.query (l, r, 1 , vl).second ;
102+ int64_t cnt = SGT.query (l, r, vr, vr).second / (vr - 1 ) - (k / (vr - 1 ) + 1 ), rest = vr - k % (vr - 1 );
103+ assert (cnt >= 0 );
104+ cout << SGT.query (l, r, vr + 1 , mod - 1 ).first * qpow (vr, cnt) % mod * rest % mod << endl;
105+ }
106+ return ;
107+ }
108+
109+ bool mem2;
110+
111+ int main () {
112+ ios::sync_with_stdio (false ), cin.tie (nullptr );
113+ #ifdef LOCAL
114+ cerr << " Memory Cost: " << abs (&mem1 - &mem2) / 1024 . / 1024 . << " MB" << endl;
115+ #endif
116+
117+ int _ = 1 ;
118+ while (_--) solve ();
119+
120+ #ifdef LOCAL
121+ cerr << " Time Cost: " << clock () * 1000 . / CLOCKS_PER_SEC << " MS" << endl;
122+ #endif
123+ return 0 ;
124+ }
0 commit comments