/** author: shobonvip created: 2025.02.14 22:36:39 **/ #pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #include using namespace std; #include #include using namespace atcoder; typedef modint998244353 mint; typedef long long ll; #define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++) #define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--) #define all(v) v.begin(), v.end() template bool chmin(T &a, const T &b) { if (a <= b) return false; a = b; return true; } template bool chmax(T &a, const T &b) { if (a >= b) return false; a = b; return true; } template T max(vector &a){ assert(!a.empty()); T ret = a[0]; for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]); return ret; } template T min(vector &a){ assert(!a.empty()); T ret = a[0]; for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]); return ret; } template T sum(vector &a){ T ret = 0; for (int i=0; i<(int)a.size(); i++) ret += a[i]; return ret; } int op(int a, int b) { return max(a, b); } int e() { return 0; } typedef bitset<18000> BTS; // importbisect template int bisect_left(vector &X, T v){ return lower_bound(X.begin(), X.end(), v) - X.begin(); } template int bisect_right(vector &X, T v){ return upper_bound(X.begin(), X.end(), v) - X.begin(); } // ----- mint plpow[100][30]; int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); const int mx = 200000; vector pl; vector pg; vector p(mx+1); rep(i,2,mx+1){ if(p[i])continue; if(i<=447) { pl.push_back(i); }else{ pg.push_back(i); } for(int j=i;j<=mx;j+=i){ p[j]=1; } } rep(i,0,(int)pl.size()){ plpow[i][0] = 1; rep(j,1,30){ plpow[i][j] = plpow[i][j-1] * pl[i]; } } int n; cin >> n; vector a(n); vector largers(n,-1); vector> seg( (int)pl.size(), segtree(n) ); rep(i,0,n) { cin >> a[i]; int tar = 0; for (int x: pl) { if (a[i] % x == 0) { int cnt = 0; while (a[i] % x == 0) { a[i] /= x; cnt++; } seg[tar].set(i, cnt); } tar++; } if (a[i] > 1) { largers[i] = bisect_left(pg,a[i]); } } const int B = 2000; int blocks = (n+B-1)/B; vector bg(blocks, vector(blocks+1)); vector bans(blocks, vector(blocks+1,1)); rep(i,0,blocks) { int cnt=0; int v=0; BTS nb; mint nans=1; rep(j,i*B,n) { if (largers[j]>=0){ if (!nb[largers[j]]){ nb[largers[j]]=1; nans*=pg[largers[j]]; } } cnt++; if(cnt==B) { v++; bg[i][i+v]=nb; bans[i][i+v]=nans; cnt=0; } } } auto query = [&](int l, int r) -> mint { assert(0<=l&&r<=n); mint ans=1; rep(i,0,(int)pl.size()) { ans *= plpow[i][seg[i].prod(l,r)]; } if (l/B==r/B) { BTS nb; rep(j,l,r){ if (largers[j]>=0){ if (!nb[largers[j]]){ nb[largers[j]]=1; ans*=a[j]; } } } }else{ int lt = l+B-(l%B); int rt = r-(r%B); BTS nb = bg[lt/B][rt/B]; ans *= bans[lt/B][rt/B]; rep(j,l,lt){ if (largers[j]>=0){ if (!nb[largers[j]]){ nb[largers[j]]=1; ans*=a[j]; } } } rep(j,rt,r){ if (largers[j]>=0){ if (!nb[largers[j]]){ nb[largers[j]]=1; ans*=a[j]; } } } } return ans; }; int q; cin >> q; ll last_ans = 1; rep(i,0,q) { ll a, b; cin >> a >> b; int l = last_ans * a % 998244353 % n; int r = last_ans * b % 998244353 % n; if (l > r) swap(l, r); r++; last_ans = query(l,r).val(); cout << last_ans << '\n'; } }