Problem:
I - Range Totient Query
Time Limit: 3 sec
問題文
長さ$N$の正整数列$A = (A_1, A_2, \dots, A_N)$が与えられます。$Q$個のクエリが与えられます。$i$番目のクエリでは、整数$L_i, R_i$が与えられます。それぞれのクエリに対して、
$$\phi\left(\prod_{j=L_i}^{R_i} A_j \right)$$
の値を$998244353$で割ったあまりを答えてください。ここで、$\phi$はEulerのtotient関数で、正整数$n$に対して$\phi(n)$は$n$と互いに素な$1$以上$n$以下の正整数の個数を表します。
制約
$1 \leq N \leq 10^5$
$1 \leq A_i \leq 10^6$
$1 \leq Q \leq 10^5$
$1 \leq L_i \leq R_i \leq N$
入力はすべて整数
入力
$N$
$A_1\quad A_2 \quad \dots\quad A_N$
$Q$
$L_1\quad R_1$
$L_2\quad R_2$
$\vdots$
$L_Q\quad R_Q$
出力
$Q$行出力せよ。
$i$行目には$i$番目のクエリの答えを出力せよ。
入力例1
7
5
9
8
1
3
8
2
4
1
3
3
7
4
4
1
7
出力例1
96
128
1
4608

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
#define int long long
#define double long double
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
int mod = 998244353;
int a[N];
ll n, tree[N], pr[M], vis[M], idx, pre[N], ans[N], las[M], inv[M];
struct Link {
    int l, r, id;
} b[N];
bool cmp(Link xx, Link yy) {
    return xx.r < yy.r;
}
ll lowbit(ll num) {
    return num & -num;
}
void build(ll s, ll num) {
    for (ll i = s; i <= n; i += lowbit(i)) tree[i] = tree[i] * num % mod;
}
ll ask(ll s) {
    ll ans = 1;
    for (ll i = s; i >= 1; i -= lowbit(i)) ans = ans * tree[i] % mod;
    return ans;
}
int ksm(int a, int b, int c) {
    a %= c;
    int ans = 1;
    while (b) {
        if (b % 2) ans = ans * a % c;
        a = a * a % c;
        b /= 2;
    }
    return ans;
}
int Inv(int x) {
    return ksm(x, mod - 2, mod);
}
void upd(int pos) {
    int sp = a[pos];
    // cout<<sp<<"\n";
    for (int i = 1; pr[i]*pr[i] <= sp; i++) {
        if (sp % pr[i] == 0) {
            // cout<<pr[i]<<"\n";
            build(pos, (pr[i] - 1)*inv[pr[i]] % mod);
            if (las[pr[i]]) build(las[pr[i]], pr[i]*inv[pr[i] - 1] % mod);
            las[pr[i]] = pos;
            while (sp % pr[i] == 0) sp /= pr[i];
        }
    }
    if (sp > 1) {
        build(pos, (sp - 1)*inv[sp] % mod);
        if (las[sp]) build(las[sp], sp * inv[sp - 1] % mod);
        las[sp] = pos;
    }
}
void solve() {
    int q;
    cin >> n ;
    pre[0] = 1;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        pre[i] = pre[i - 1] * a[i] % mod;
    }
cin>>q;
    for (int i = 0; i <= 2e5; i++) tree[i] = 1;
    inv[1] = 1;
    for (int i = 2; i <= 1e6; i++) {
        inv[i] = ((mod - mod / i) * inv[mod % i] ) % mod;
        if (!vis[i]) {
            vis[i] = 1;
            pr[++idx] = i;
        }
        for (int j = 1; j <= idx; j++) {
            if (pr[j]*i > 1e6) break;
            vis[pr[j]*i] = 1;
            if (i % pr[j] == 0) break;
        }
    }
    for (int i = 1; i <= q; i++) {
        cin >> b[i].l >> b[i].r;
        b[i].id = i;
    }
    sort(b + 1, b + q + 1, cmp);
    // for(int i=1;i<=q;i++) cout<<b[i].l<<" "<<b[i].r<<"\n";
    int pos = 0;
    for (int i = 1; i <= q; i++) {
        while (pos < b[i].r) pos++, upd(pos);
        ans[b[i].id] = pre[b[i].r] * Inv(pre[b[i].l - 1]) % mod * ask(
                           b[i].r) % mod * Inv(ask(b[i].l - 1)) % mod;
        // cout<<sl<<"\n";
    }
    for (int i = 1; i <= q; i++) cout << ans[i] << "\n";
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int _;
    _ = 1;
    //cin>>_;
    while (_--) {
        solve();
    }
}
accuracy: 1
time_ms: 230
memory_kb: 38700
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
namespace fastIO{static char BUF[1000000],*P1=BUF,*P2=BUF,OBUF[1000000],*P3=OBUF;inline char gc(){return P1==P2&&(P2=(P1=BUF)+fread(BUF,1,1000000,stdin),P1==P2)?EOF:*P1++;}inline void pc(register char x){(P3-OBUF<1000000)?(*P3++=x):(fwrite(OBUF,P3-OBUF,1,stdout),P3=OBUF,*P3++=x);}template<typename item>inline void uread(register item&x){register char c;for(;c=gc(),c<48||c>57;);for(x=c^48;c=gc(),c>=48&&c<=57;)x=(x<<3)+(x<<1)+(c^48);}template<typename item>inline void read(register item&x){register char c;register bool f=0;for(;c=gc(),c<48||c>57;)if(c==45)f=1;for(x=c^48;c=gc(),c>=48&&c<=57;)x=(x<<3)+(x<<1)+(c^48);f&&(x=-x);}static char STACK[40];template<typename item>inline void uwrite(register item x){if(!x)return pc('0');register unsigned short len=0;for(;x;x/=10)STACK[len++]=x%10|48;for(;len--;)pc(STACK[len]);}template<typename item>inline void write(register item x){if(!x)return pc('0');if(x<0)pc('-'),x=-x;register unsigned short len=0;for(;x;x/=10)STACK[len++]=x%10;for(;len--;)pc(STACK[len]|48);}inline void close(){fwrite(OBUF,P3-OBUF,1,stdout);}}
using namespace fastIO;
#define space() pc(' ')
#define endl() pc('\n')
using U=unsigned;using ll=long long;using ull=unsigned long long;using lll=__int128_t;using ulll=__uint128_t;using db=double;using ld=long db;using pii=pair<int,int>;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define il inline
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());int Rnd(int l,int r){return rnd()%(r-l+1)+l;}
const vector<int>P{2,7,61};
inline ll qpow(ll a,ll b,const ll mod){ll ret=1;for(;b;b>>=1,a=(__int128)a*a%mod)if(b&1)ret=(__int128)ret*a%mod;return ret;}
inline int chk(const ll b,const ll p){
	if(!(p%b))return p==b?1:0;
	if(qpow(b,p-1,p)!=1)return 0;
	ll t=p-1,v;
	while(!(t&1)){
		t>>=1,v=qpow(b,t,p);
		if(v!=1)return v==p-1;
	}return 1;
}inline int ispr(const ll p){if(p==1)return 0;for(int c:P)if(!chk(c,p))return 0;return 1;}
inline ll slv(const ll p,const int c){
	int cnt=0,k=1;ll v0=Rnd(1,p-1),v=v0,tmp,s=1;
	for(;;){
		v=((__int128)v*v+c)%p,s=(__int128)s*abs(v0-v)%p;
		if(v==v0||!s)return p;
		if(++cnt==k){tmp=__gcd(s,p);if(tmp!=1)return tmp;v0=v,k<<=1;}
	}
}ll ans;
void get(ll p,int c){
	if(p==1||p<=ans)return;
	if(ispr(p))return ans=max(ans,p),void();
	ll tmp=c;while((tmp=slv(p,c--))==p);while(!(p%tmp))p/=tmp;get(p,c),get(tmp,c);
}inline ll qmx(ll p){ans=-1,get(p,rnd());return ans;}
const int N=2e5+9,V=1e6+9,B=250,mod=998244353;
int n,q,res=1,a[N],bl[N],pr[B+9],s[N][100],cnt[V],aans[N];vector<pair<pii,pair<pii,pii>>>v[N];
struct _{int l,r,id;}qy[N];
il int qpow(register int a,register int b){int ret=1;for(;b;a=1ll*a*a%mod,b>>=1)if(b&1)ret=1ll*ret*a%mod;return ret;}
il void add(const register int x){
	for(auto i:v[x]){
		const register int p=i.fi.fi,c=i.fi.se,v1=i.se.fi.fi,v2=i.se.se.fi;
		if(!cnt[p])res=1ll*res*v1%mod;
		else res=1ll*res*v2%mod;
		cnt[p]+=c;
	}
}il void del(const register int x){
	for(auto i:v[x]){
		const register int p=i.fi.fi,c=i.fi.se,iv1=i.se.fi.se,iv2=i.se.se.se;
		if(cnt[p]^c)res=1ll*res*iv2%mod;
		else res=1ll*res*iv1%mod;
		cnt[p]-=c;
	}
}
int main(){//freopen("phi.in","r",stdin),freopen("phi.out","w",stdout);
	for(int i=2;i<=B;i++)if(ispr(i))pr[++pr[0]]=i;//cerr<<pr[0]<<'\n';
	uread(n);const int len=sqrt(n)*2;
	for(int i=1,x;i<=n;i++){
		uread(x),bl[i]=(i-1)/len+1;
		for(int j=1;j<=pr[0]&&(x^1);j++)while(!(x%pr[j]))x/=pr[j],++s[i][j];
		while(x^1){
			int cnt=0;
			for(qmx(x);!(x%ans);)x/=ans,++cnt;
			v[i].pb({{ans,cnt},{{1ll*qpow(ans,cnt-1)*(ans-1)%mod,qpow(1ll*qpow(ans,cnt-1)*(ans-1)%mod,mod-2)},{qpow(ans,cnt),qpow(qpow(ans,cnt),mod-2)}}});
		}
	}for(int i=1;i<=n;i++)for(int j=1;j<=pr[0];j++)s[i][j]+=s[i-1][j];
	uread(q);
	for(int i=1;i<=q;i++)uread(qy[i].l),uread(qy[i].r),qy[i].id=i;
	sort(qy+1,qy+q+1,[](_ x,_ y){return bl[x.l]==bl[y.l]?bl[x.l]&1?x.r<y.r:x.r>y.r:bl[x.l]<bl[y.l];});
	for(int i=1,l=1,r=0;i<=q;i++){
		const register int L=qy[i].l,R=qy[i].r;
		while(l>L)add(--l);
		while(r<R)add(++r);
		while(l<L)del(l++);
		while(r>R)del(r--);
		register int tmp=res;
		for(register int j=1;j<=pr[0];j++)if(s[R][j]-s[L-1][j])tmp=1ll*tmp*qpow(pr[j],s[R][j]-s[L-1][j]-1)%mod*(pr[j]-1)%mod;
		aans[qy[i].id]=tmp;
	}for(int i=1;i<=q;i++)uwrite(aans[i]),endl();
	return close(),0;
}
accuracy: 1
time_ms: 470
memory_kb: 62096
final_rank: 6

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define N 200005
#define M 180
#define space() pc(' ')
#define endl() pc('\n')
namespace fastIO{static char BUF[1000000],*P1=BUF,*P2=BUF,OBUF[1000000],*P3=OBUF;inline char gc(){return P1==P2&&(P2=(P1=BUF)+fread(BUF,1,1000000,stdin),P1==P2)?EOF:*P1++;}inline void pc(register char x){(P3-OBUF<1000000)?(*P3++=x):(fwrite(OBUF,P3-OBUF,1,stdout),P3=OBUF,*P3++=x);}template<typename item>inline void uread(register item&x){register char c;for(;c=gc(),c<48||c>57;);for(x=c^48;c=gc(),c>=48&&c<=57;)x=(x<<3)+(x<<1)+(c^48);}template<typename item>inline void read(register item&x){register char c;register bool f=0;for(;c=gc(),c<48||c>57;)if(c==45)f=1;for(x=c^48;c=gc(),c>=48&&c<=57;)x=(x<<3)+(x<<1)+(c^48);f&&(x=-x);}static char STACK[40];template<typename item>inline void uwrite(register item x){if(!x)return pc('0');register unsigned short len=0;for(;x;x/=10)STACK[len++]=x%10|48;for(;len--;)pc(STACK[len]);}template<typename item>inline void write(register item x){if(!x)return pc('0');if(x<0)pc('-'),x=-x;register unsigned short len=0;for(;x;x/=10)STACK[len++]=x%10;for(;len--;)pc(STACK[len]|48);}inline void close(){fwrite(OBUF,P3-OBUF,1,stdout);}}
using namespace fastIO;
using namespace std; 
int n;
const int maxn=1e3,mod=998244353,mn=1e6;
int a[N];
int cnt,pr[N];
bitset<mn+5> vis;
int num[N][M];
int q;
struct node{
	int l,r,id;
}e[N];
inline int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=1ll*res*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return res;
}
int ans[N];
int B;
int belong[N];
int inv[N*5];
int pre[N*5];
inline bool cmp(node x,node y){
	if(belong[x.l]==belong[y.l]){
		if(belong[x.l]&1)return x.r<y.r;
		else return x.r>y.r;
	}
	else return x.l<y.l;
}
int sum[N*5];
int res=1;
int p[N*5];
int fid[10005];
inline void add(int x,int v){
	if(a[x]==1) return;
	if(v==1){
		sum[a[x]]++;
		if(sum[a[x]]==1) res=1ll*res*(a[x]-1)%mod;
		else res=1ll*res*a[x]%mod;
	}
	else{
		sum[a[x]]--;
		if(sum[a[x]]>=1) res=1ll*res*inv[a[x]]%mod;
		else res=1ll*res*inv[a[x]-1]%mod;
	}
}
int main(){
	uread(n);
	B=sqrt(n);
	for(int i=1;i<=n;i++) uread(a[i]),belong[i]=(i-1)/B+1;
	vis[1]=1;
	for(int i=2;i<=mn;i++){
		if(!vis[i]) pr[++cnt]=i,p[i]=i;
		for(int j=1;j<=cnt and i*pr[j]<=mn;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0){
				p[i*pr[j]]=p[i];
				break;
			}
			else{
				p[i*pr[j]]=pr[j];
			}
		}
	}
	pre[0]=1;
	for(int i=1;i<=mn;i++){
		pre[i]=1ll*pre[i-1]*i%mod;
	}
	int y=qpow(pre[mn],mod-2);
	for(int i=mn;i>=1;i--){
		inv[i]=1ll*y*pre[i-1]%mod;
		y=1ll*y*i%mod;
	}
	cnt=168;
	for(int j=1;j<=cnt;j++){
		fid[pr[j]]=j;
	}
	for(int i=1;i<=n;i++){
		int x=a[i];
		while(x!=1){
			if(p[x]>1000) break;
			num[i][fid[p[x]]]++;
			x/=p[x];
		}
		a[i]=x;
		for(int j=1;j<=cnt;j++) num[i][j]+=num[i-1][j];
	}
	uread(q);
	for(int i=1;i<=q;i++){
		uread(e[i].l),uread(e[i].r);
		ans[i]=1;
		for(int j=1;j<=cnt;j++){
			int x=num[e[i].r][j]-num[e[i].l-1][j];
			if(x) ans[i]=ans[i]*1ll*(pr[j]-1)%mod*qpow(pr[j],x-1)%mod;
		}
		e[i].id=i;
	}
	res=1;
	sort(e+1,e+q+1,cmp);
	for(int i=1,l=1,r=0;i<=q;i++){
		while(l>e[i].l){
			l--;
			add(l,1);
		}
		while(r<e[i].r){
			r++;
			add(r,1);
		}
		while(l<e[i].l){
			add(l,-1);
			l++;
		}
		while(r>e[i].r){
			add(r,-1);
			r--;
		}
		ans[e[i].id]=1ll*ans[e[i].id]*res%mod;
	}
	for(int i=1;i<=q;i++){
		uwrite(ans[i]);
		endl();
	}
	close();
	return 0;
}
accuracy: 1
time_ms: 660
memory_kb: 97552
final_rank: 10

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define N 200005
#define M 180
using namespace std; 
int n;
const int maxn=1e3,mod=998244353,mn=1e6;
int a[N];
int cnt,pr[M];
bool vis[N];
int num[N][M];
int q;
struct node{
	int l,r,id;
}e[N];
int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=1ll*res*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return res;
}
int ans[N];
int B;
int belong[N];
int inv[N*5];
int pre[N*5],inv_pre[N*5];
inline bool cmp(node x,node y){
	if(belong[x.l]==belong[y.l]){
		return x.r<y.r;
	}
	else return x.l<y.l;
}
int sum[N*5];
int res=1;
inline void add(int x,int v){
	if(v==1){
		sum[a[x]]++;
		if(a[x]==1) return ;
		if(sum[a[x]]==1) res=1ll*res*(a[x]-1)%mod;
		else res=1ll*res*a[x]%mod;
	}
	else{
		sum[a[x]]--;
		if(a[x]==1) return;
		if(sum[a[x]]>=1) res=1ll*res*inv[a[x]]%mod;
		else res=1ll*res*inv[a[x]-1]%mod;
	}
}
int main(){
	cin.tie(),cout.tie(),ios::sync_with_stdio(0);
	cin>>n;
	B=sqrt(n);
	for(int i=1;i<=n;i++) cin>>a[i],belong[i]=(i-1)/B+1;
	vis[1]=1;
	for(int i=2;i<=maxn;i++){
		if(!vis[i]) pr[++cnt]=i;
		for(int j=1;j<=cnt and i*pr[j]<=maxn;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0) break;
		}
	}
	pre[0]=1;
	for(int i=1;i<=mn;i++){
		pre[i]=1ll*pre[i-1]*i%mod;
	}
	inv_pre[mn]=qpow(pre[mn],mod-2);
	for(int i=mn-1;i>=1;i--){
		inv_pre[i]=1ll*inv_pre[i+1]*(i+1)%mod;
	}
	inv_pre[0]=1;
	for(int i=1;i<=mn;i++){
		inv[i]=1ll*inv_pre[i]*pre[i-1]%mod;
	}
	for(int i=1;i<=n;i++){
		int x=a[i];
		for(int j=1;j<=cnt;j++){
			if(x==1) break;
			while(x%pr[j]==0){
				x/=pr[j];
				num[i][j]++;
			}
		}
		a[i]=x;
	}
	for(int j=1;j<=cnt;j++){
		for(int i=1;i<=n;i++){
			num[i][j]+=num[i-1][j];
		}
	}
	cin>>q;
	for(int i=1;i<=q;i++){
		cin>>e[i].l>>e[i].r;
		ans[i]=1;
		for(int j=1;j<=cnt;j++){
			int x=num[e[i].r][j]-num[e[i].l-1][j];
			if(x) ans[i]=ans[i]*1ll*(pr[j]-1)%mod*qpow(pr[j],x-1)%mod;
		}
		e[i].id=i;
	}
	res=1;
	sort(e+1,e+q+1,cmp);
	for(int i=1,l=1,r=0;i<=q;i++){
		while(l>e[i].l){
			l--;
			add(l,1);
		}
		while(r<e[i].r){
			r++;
			add(r,1);
		}
		while(l<e[i].l){
			add(l,-1);
			l++;
		}
		while(r>e[i].r){
			add(r,-1);
			r--;
		}
		ans[e[i].id]=1ll*ans[e[i].id]*res%mod;
	}
	for(int i=1;i<=q;i++){
		cout<<ans[i]<<'\n';
	}
	return 0;
}
accuracy: 1
time_ms: 800
memory_kb: 93964
final_rank: 11

code_snippet: // AOJ #3262
// Range Totient Query 2025.2.7

#include <bits/stdc++.h>
using namespace std;
using ll = long long; 
const ll MOD = 998244353;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

ll modexp(ll base, ll exp, ll mod) {
    ll result = 1;
    base %= mod;
    while(exp > 0){
        if(exp & 1) result = (result * base) % mod;
        base = (base * base) % mod;
        exp >>= 1;
    }
    return result;
}
 
ll modInv(ll x, ll mod) {
    return modexp(x, mod-2, mod);
}
 
struct Fenw {
    int n;
    vector<ll> fenw;
    Fenw(int n) : n(n) {
        fenw.assign(n+1, 1);
    }
    void update(int i, ll val) {
        for(; i <= n; i += i & -i){
            fenw[i] = (fenw[i] * val) % MOD;
        }
    }
    ll query(int i) {
        ll res = 1;
        for(; i > 0; i -= i & -i)
            res = (res * fenw[i]) % MOD;
        return res;
    }
    ll rangeQuery(int l, int r) {
        if(l > r) return 1;
        ll q = query(r);
        ll invPrefix = modInv(query(l-1), MOD);
        return (q * invPrefix) % MOD;
    }
};
 
vector<int> sieve_spf(int maxN) {
    vector<int> spf(maxN+1);
    for (int i = 0; i <= maxN; i++) {
        spf[i] = i;
    }
    for (int i = 2; i * i <= maxN; i++) {
        if(spf[i] == i){
            for (int j = i*i; j <= maxN; j += i) {
                if(spf[j] == j)
                    spf[j] = i;
            }
        }
    }
    return spf;
}
 
vector<int> getDistinctPrimes(int x, const vector<int> &spf) {
    vector<int> primes;
    while(x > 1) {
        int p = spf[x];
        primes.push_back(p);
        while(x % p == 0) x /= p;
    }
    return primes;
}
 
struct Query { int L, R, idx; };
 
int main(){
    int N = Cin();
    vector<int> A(N+1);
    for (int i = 1; i <= N; i++) A[i] = Cin();
 
    vector<ll> pref(N+1, 1);
    for (int i = 1; i <= N; i++){
        pref[i] = (pref[i-1] * A[i]) % MOD;
    }
 
    int Q = Cin();
    vector<Query> queries(Q);
    for (int i = 0; i < Q; i++){
        int L = Cin(), R = Cin();
        queries[i] = {L, R, i};
    }
    sort(queries.begin(), queries.end(), [](const Query &a, const Query &b){
        return a.R < b.R;
    });
 
    int maxA = 1000000;
    vector<int> spf = sieve_spf(maxA);
 
    vector<ll> inv(maxA+2, 1);
    inv[1] = 1;
    for (int i = 2; i <= maxA+1; i++){
        inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD;
    }
 
    Fenw fenw(N);
    vector<int> lastOccurrence(maxA+1, 0);
 
    vector<ll> ans(Q, 0);
    int qptr = 0;
    for (int i = 1; i <= N; i++){
        if(A[i] != 1){
            vector<int> primes = getDistinctPrimes(A[i], spf);
            for (int p : primes) {
                if(lastOccurrence[p] != 0){
                    ll removeVal = ( (ll)p * inv[p-1] ) % MOD;
                    fenw.update(lastOccurrence[p], removeVal);
                }
                ll addVal = ((ll)(p-1) * inv[p]) % MOD;
                fenw.update(i, addVal);
                lastOccurrence[p] = i;
            }
        }
        while(qptr < Q && queries[qptr].R == i){
            int L = queries[qptr].L, R = queries[qptr].R;
            ll prodA = (pref[R] * modInv(pref[L-1], MOD)) % MOD;
            ll prodBIT = fenw.rangeQuery(L, R);
            ll res = (prodA * prodBIT) % MOD;
            ans[queries[qptr].idx] = res;
            qptr++;
        }
    }
    for (int i = 0; i < Q; i++) Cout(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 22512
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
	const int MOD = 998244353;

	// step #1. input
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N;
	cin >> N;
	vector<int> A(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}
	int Q;
	cin >> Q;
	vector<int> L(Q), R(Q);
	for (int i = 0; i < Q; i++) {
		cin >> L[i] >> R[i];
		L[i] -= 1;
	}

	// step #2. sieve
	int limit = *max_element(A.begin(), A.end()) + 1;
	vector<vector<int> > factor(limit + 1);
	for (int i = 2; i <= limit; i++) {
		if (factor[i].empty()) {
			for (int j = i; j <= limit; j += i) {
				factor[j].push_back(i);
			}
		}
	}

	// step #3. segment tree
	int sz = (N >= 3 ? 1 << (32 - __builtin_clz(N - 1)) : N);
	vector<int> val(sz * 2);
	auto update = [&](int pos, int x) -> void {
		pos += sz;
		val[pos] = x;
		while (pos > 1) {
			pos /= 2;
			val[pos] = 1LL * val[pos * 2] * val[pos * 2 + 1] % MOD;
		}
	};
	auto rangeprod = [&](int l, int r) -> int {
		l += sz;
		r += sz;
		int ans = 1;
		while (l != r) {
			if (l & 1) ans = 1LL * ans * val[l++] % MOD;
			if (r & 1) ans = 1LL * ans * val[--r] % MOD;
			l /= 2;
			r /= 2;
		}
		return ans;
	};

	// step #4. process queries
	vector<vector<int> > qs(N);
	for (int i = 0; i < Q; i++) {
		qs[R[i] - 1].push_back(i);
	}
	vector<int> pre(limit + 1, -1);
	vector<int> ans(Q);
	for (int i = 0; i < N; i++) {
		int x = A[i];
		for (int j : factor[A[i]]) {
			if (pre[j] != -1) {
				update(pre[j], val[sz + pre[j]] / (j - 1) * j);
			}
			pre[j] = i;
			x = x / j * (j - 1);
		}
		update(i, x);
		for (int j : qs[i]) {
			ans[j] = rangeprod(L[j], i + 1);
		}
	}

	// step #5. output
	for (int i = 0; i < Q; i++) {
		cout << ans[i] << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 68992
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int MOD=998244353;
constexpr int MAX_A=1e6+7;
constexpr int sqN=320;

ll modpow(ll a,ll n){
  ll ret=1,t=a;
  while(n>0){
    if(n%2)ret=ret*t%MOD;
    t=t*t%MOD;
    n/=2;
  }
  return ret;
}

int main(){
  ios::sync_with_stdio(0);
  cin.tie(0);
  vector pf(MAX_A,0),inv(MAX_A,0);
  iota(pf.begin(),pf.end(),0);
  for(ll i=2;i<MAX_A;i++){
    if(pf[i]!=i)continue;
    for(ll j=i*2;j<MAX_A;j+=i){
      if(pf[j]==j)pf[j]=i;
    }
  }
  for(int i=0;i<MAX_A;i++)inv[i]=modpow(i,MOD-2);
  int N;
  cin>>N;
  vector A(N,0);
  for(int &i:A)cin>>i;
  vector Apf(N,vector(0,array<int,2>()));
  for(int i=0;i<N;i++){
    int k=A[i];
    while(k>1){
      int p=pf[k],e=0;
      while(pf[k]==p){
        e+=1;
        k/=p;
      }
      Apf[i].push_back({p,e});
    }
  }
  int Q;
  cin>>Q;
  vector Qs(Q,array<int,3>());
  for(int i=0;i<Q;i++){
    cin>>Qs[i][0]>>Qs[i][1];
    Qs[i][0]-=1;
    Qs[i][2]=i;
  }
  sort(Qs.begin(),Qs.end(),[](array<int,3> a,array<int,3>b){
    if(a[0]/sqN==b[0]/sqN){
      if(a[0]/sqN%2){
        return a[1]>b[1];
      }else{
        return a[1]<b[1];
      }
    }else{
      return a[0]/sqN<b[0]/sqN;
    }
  });
  vector ans(Q,0),cnt(MAX_A,0);
  auto add=[&Apf,&A,&inv](ll n,ll i,vector<int>& cnt){
    for(auto [p,e]:Apf[i]){
      if(cnt[p]==0){
        n=n*(p-1)%MOD*inv[p]%MOD;
      }
      cnt[p]+=e;
    }
    n=n*A[i]%MOD;
    return n;
  };
  auto del=[&Apf,&A,&inv](ll n,ll i,vector<int>& cnt){
    for(auto [p,e]:Apf[i]){
      cnt[p]-=e;
      if(cnt[p]==0){
        n=n*p%MOD*inv[p-1]%MOD;
      }
    }
    n=n*inv[A[i]]%MOD;
    return n;
  };
  for(ll i=0,L=0,R=0,now=1;i<Q;i++){
    auto [L2,R2,idx]=Qs[i];
    while(L>L2){
      L-=1;
      now=add(now,L,cnt);
    }
    while(R<R2){
      now=add(now,R,cnt);
      R+=1;
    }
    while(L<L2){
      now=del(now,L,cnt);
      L+=1;
    }
    while(R>R2){
      R-=1;
      now=del(now,R,cnt);
    }
    ans[idx]=now;
  }
  for(auto i:ans)cout<<i<<'\n';
}
accuracy: 1
time_ms: 360
memory_kb: 26744
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
	const int MOD = 998244353;

	// step #1. input
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N;
	cin >> N;
	vector<int> A(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}
	int Q;
	cin >> Q;
	vector<int> L(Q), R(Q);
	for (int i = 0; i < Q; i++) {
		cin >> L[i] >> R[i];
		L[i] -= 1;
	}

	// step #2. sieve
	int limit = *max_element(A.begin(), A.end()) + 1;
	vector<vector<int> > factor(limit + 1);
	for (int i = 2; i <= limit; i++) {
		if (factor[i].empty()) {
			for (int j = i; j <= limit; j += i) {
				factor[j].push_back(i);
			}
		}
	}

	// step #3. segment tree
	int sz = (N >= 3 ? 1 << (32 - __builtin_clz(N - 1)) : N);
	vector<int> val(sz * 2);
	auto update = [&](int pos, int x) -> void {
		pos += sz;
		val[pos] = x;
		while (pos > 1) {
			pos /= 2;
			val[pos] = 1LL * val[pos * 2] * val[pos * 2 + 1] % MOD;
		}
	};
	auto rangeprod = [&](int l, int r) -> int {
		l += sz;
		r += sz;
		int ans = 1;
		while (l != r) {
			if (l & 1) ans = 1LL * ans * val[l++] % MOD;
			if (r & 1) ans = 1LL * ans * val[--r] % MOD;
			l /= 2;
			r /= 2;
		}
		return ans;
	};

	// step #4. process queries
	vector<vector<int> > qs(N);
	for (int i = 0; i < Q; i++) {
		qs[R[i] - 1].push_back(i);
	}
	vector<int> pre(limit + 1, -1);
	vector<int> ans(Q);
	for (int i = 0; i < N; i++) {
		int x = A[i];
		for (int j : factor[A[i]]) {
			if (pre[j] != -1) {
				update(pre[j], val[sz + pre[j]] / (j - 1) * j);
			}
			pre[j] = i;
			x = x / j * (j - 1);
		}
		update(i, x);
		for (int j : qs[i]) {
			ans[j] = rangeprod(L[j], i + 1);
		}
	}

	// step #5. output
	for (int i = 0; i < Q; i++) {
		cout << ans[i] << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 68936
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

long long modpow(long long a, long long b, long long m) {
    long long p = 1, q = a;
    for (int i = 0; i < 30; i++) {
        if ((b >> i) & 1) { p *= q; p %= m; }
        q *= q; q %= m;
    }
    return p;
}

long long Division(long long a, long long b, long long m) {
    return (a * modpow(b, m - 2, m)) % m;
}

long long mod = 998244353;
long long N, A[1 << 20];
long long Q, L[1 << 20], R[1 << 20];
long long Prod1[1 << 20];
long long Prod2[1 << 20];
long long Kake1[1 << 20];
long long Kake2[1 << 20];
long long Cnt[1 << 20];
long long Answer = 1;
long long FinalAns[1 << 20];
vector<int> Yaku[1 << 20];
vector<pair<int, int>> List[1 << 20];

void Add(int pos) {
    for (int val : Yaku[pos]) {
        Cnt[val] += 1;
        if (Cnt[val] == 1) Answer = (Answer * Kake1[val]) % mod;
    }
}

void Del(int pos) {
    for (int val : Yaku[pos]) {
        Cnt[val] -= 1;
        if (Cnt[val] == 0) Answer = (Answer * Kake2[val]) % mod;
    }
}

long long GetRange(int cl, int cr) {
    return Prod1[cr] * Prod2[cl - 1] % mod;
}

void Prepare() {
    // Calculate Prod & Kake
    Prod1[0] = 1;
    for (int i = 1; i <= N; i++) Prod1[i] = (Prod1[i - 1] * A[i]) % mod;
    for (int i = 0; i <= N; i++) Prod2[i] = Division(1, Prod1[i], mod);
    for (int i = 1; i <= 1000000; i++) Kake1[i] = Division(i - 1, i, mod);
    for (int i = 1; i <= 1000000; i++) Kake2[i] = Division(i, i - 1, mod);

    // Enumerate Yaku
    for (int i = 1; i <= N; i++) {
        int cx = A[i];
        for (int j = 2; j * j <= cx; j++) {
            if (cx % j != 0) continue;
            Yaku[i].push_back(j);
            while (cx % j == 0) cx /= j;
        }
        if (cx >= 2) Yaku[i].push_back(cx);
    }
}

int main() {
    // Step 1. Input
    cin >> N;
    for (int i = 1; i <= N; i++) cin >> A[i];
    cin >> Q;
    for (int i = 1; i <= Q; i++) cin >> L[i] >> R[i];

    // Step 2. Prepare
    int BACKET = max(1, (int)sqrt(N));
    Prepare();
    for (int i = 1; i <= Q; i++) List[L[i] / BACKET].push_back(make_pair(R[i], i));
    for (int i = 0; i <= N; i++) sort(List[i].begin(), List[i].end());

    // Step 3. Mo's Algorithm
    int cl = 1;
    int cr = 0;
    for (int i = 0; i <= N; i++) {
        for (int j = 0; j < (int)List[i].size(); j++) {
            int idx = List[i][j].second;
            int pl = L[idx];
            int pr = R[idx];
            while (cl > pl) { cl--; Add(cl); }
            while (cl < pl) { Del(cl); cl++; }
            while (cr < pr) { cr++; Add(cr); }
            while (cr > pr) { Del(cr); cr--; }
            long long val1 = GetRange(pl, pr);
            FinalAns[idx] = val1 * Answer % mod;
        }
    }

    // Step 4. Output
    for (int i = 1; i <= Q; i++) cout << FinalAns[i] << endl;
    return 0;
}
accuracy: 1
time_ms: 1380
memory_kb: 93720
final_rank: 12

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 3262.cc: I - Range Totient Query
 */

#include<cstdio>
#include<vector>
#include<algorithm>
#include<utility>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_QN = 100000;
const int MAX_P = 1000;
const int MOD = 998244353;

/* typedef */

typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;

template<const int MOD>
struct MI {
  int v;
  MI(): v() {}
  MI(int _v): v(_v % MOD) {}
  MI(long long _v): v(_v % MOD) {}

  MI operator+(const MI m) const { return MI(v + m.v); }
  MI operator-(const MI m) const { return MI(v + MOD - m.v); }
  MI operator*(const MI m) const { return MI((long long)v * m.v); }

  MI &operator+=(const MI m) { return (*this = *this + m); }
  MI &operator-=(const MI m) { return (*this = *this - m); }
  MI &operator*=(const MI m) { return (*this = *this * m); }

  bool operator==(const MI m) const { return v == m.v; }
  bool operator!=(const MI m) const { return v != m.v; }

  MI pow(int n) const {  // a^n % MOD
    MI pm = 1, a = *this;
    while (n > 0) {
      if (n & 1) pm *= a;
      a *= a;
      n >>= 1;
    }
    return pm;
  }

  MI inv() const { return pow(MOD - 2); }
  MI operator/(const MI m) const { return *this * m.inv(); }
  MI &operator/=(const MI m) { return (*this = *this / m); }
};

typedef MI<MOD> mi;

/* global variables */

bool primes[MAX_P + 1];
int as[MAX_N], cis[MAX_N], fs[MAX_N];
vpii pds[MAX_N];
vi lvs[MAX_N], rvs[MAX_N];
mi tts[MAX_QN];

/* subroutines */

int gen_primes(int maxp, vi &pnums) {
  fill(primes, primes + maxp + 1, true);
  primes[0] = primes[1] = false;

  int p;
  for (p = 2; p * p <= maxp; p++)
    if (primes[p]) {
      pnums.push_back(p);
      for (int q = p * p; q <= maxp; q += p) primes[q] = false;
    }
  for (; p <= maxp; p++)
    if (primes[p]) pnums.push_back(p);
  return (int)pnums.size();
}

bool prime_decomp(int n, vi &pnums, vpii& pds) {
  pds.clear();

  int pn = pnums.size();
  for (int i = 0; i < pn; i++) {
    int pi = pnums[i];
    if (pi * pi > n) {
      if (n > 1) pds.push_back(pii(n, 1));
      return true;
    }

    if (n % pi == 0) {
      int fi = 0;
      while (n % pi == 0) n /= pi, fi++;
      pds.push_back(pii(pi, fi));
    }
  }
  return false;
}

/* main */

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++) scanf("%d", as + i);

  int qn;
  scanf("%d", &qn);
  for (int i = 0; i < qn; i++) {
    int l, r;
    scanf("%d%d", &l, &r);
    l--, r--;
    lvs[l].push_back(i);
    rvs[r].push_back(i);
  }

  vi pnums;
  gen_primes(MAX_P, pnums);

  vi pps;
  for (int i = 0; i < n; i++) {
    prime_decomp(as[i], pnums, pds[i]);
    for (auto pd: pds[i]) pps.push_back(pd.first);
  }
  sort(pps.begin(), pps.end());
  pps.erase(unique(pps.begin(), pps.end()), pps.end());

  fill(tts, tts + qn, 1);
  for (auto pi: pps) {
    int f = 0;
    for (int i = 0; i < n; i++) {
      for (auto u: lvs[i]) fs[u] = f;

      if (cis[i] < pds[i].size() && pi == pds[i][cis[i]].first)
	f += pds[i][cis[i]++].second;

      for (auto u: rvs[i])
	if (f > fs[u]) {
	  int e = f - fs[u];
	  tts[u] *= mi(pi).pow(e) - mi(pi).pow(e - 1);
	  //printf("tts[%d] *= %d^%d - %d^%d\n", u, pi, e, pi, e - 1);
	}
    }
  }

  for (int i = 0; i < qn; i++) printf("%d\n", tts[i].v);

  return 0;
}
accuracy: 0.3548387096774194
time_ms: 10
memory_kb: 11240
final_rank: 15

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 3262.cc: I - Range Totient Query
 */

#include<cstdio>
#include<vector>
#include<algorithm>
#include<utility>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_QN = 100000;
const int MAX_P = 1000;
const int MOD = 998244353;

/* typedef */

typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;

template<const int MOD>
struct MI {
  int v;
  MI(): v() {}
  MI(int _v): v(_v % MOD) {}
  MI(long long _v): v(_v % MOD) {}

  MI operator+(const MI m) const { return MI(v + m.v); }
  MI operator-(const MI m) const { return MI(v + MOD - m.v); }
  MI operator*(const MI m) const { return MI((long long)v * m.v); }

  MI &operator+=(const MI m) { return (*this = *this + m); }
  MI &operator-=(const MI m) { return (*this = *this - m); }
  MI &operator*=(const MI m) { return (*this = *this * m); }

  bool operator==(const MI m) const { return v == m.v; }
  bool operator!=(const MI m) const { return v != m.v; }

  MI pow(int n) const {  // a^n % MOD
    MI pm = 1, a = *this;
    while (n > 0) {
      if (n & 1) pm *= a;
      a *= a;
      n >>= 1;
    }
    return pm;
  }

  MI inv() const { return pow(MOD - 2); }
  MI operator/(const MI m) const { return *this * m.inv(); }
  MI &operator/=(const MI m) { return (*this = *this / m); }
};

typedef MI<MOD> mi;

/* global variables */

bool primes[MAX_P + 1];
int as[MAX_N], cis[MAX_N], fs[MAX_N];
vpii pds[MAX_N];
vi lvs[MAX_N], rvs[MAX_N];
mi tts[MAX_QN];

/* subroutines */

int gen_primes(int maxp, vi &pnums) {
  fill(primes, primes + maxp + 1, true);
  primes[0] = primes[1] = false;

  int p;
  for (p = 2; p * p <= maxp; p++)
    if (primes[p]) {
      pnums.push_back(p);
      for (int q = p * p; q <= maxp; q += p) primes[q] = false;
    }
  for (; p <= maxp; p++)
    if (primes[p]) pnums.push_back(p);
  return (int)pnums.size();
}

bool prime_decomp(int n, vi &pnums, vpii& pds) {
  pds.clear();

  int pn = pnums.size();
  for (int i = 0; i < pn; i++) {
    int pi = pnums[i];
    if (pi * pi > n) {
      if (n > 1) pds.push_back(pii(n, 1));
      return true;
    }

    if (n % pi == 0) {
      int fi = 0;
      while (n % pi == 0) n /= pi, fi++;
      pds.push_back(pii(pi, fi));
    }
  }
  return false;
}

/* main */

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++) scanf("%d", as + i);

  int qn;
  scanf("%d", &qn);
  for (int i = 0; i < qn; i++) {
    int l, r;
    scanf("%d%d", &l, &r);
    l--, r--;
    lvs[l].push_back(i);
    rvs[r].push_back(i);
  }

  vi pnums;
  gen_primes(MAX_P, pnums);

  vi pps;
  for (int i = 0; i < n; i++) {
    prime_decomp(as[i], pnums, pds[i]);
    for (auto pd: pds[i]) pps.push_back(pd.first);
  }
  sort(pps.begin(), pps.end());
  pps.erase(unique(pps.begin(), pps.end()), pps.end());

  fill(tts, tts + n, 1);
  for (auto pi: pps) {
    int f = 0;
    for (int i = 0; i < n; i++) {
      for (auto u: lvs[i]) fs[u] = f;

      if (cis[i] < pds[i].size() && pi == pds[i][cis[i]].first)
	f += pds[i][cis[i]++].second;

      for (auto u: rvs[i])
	if (f > fs[u]) {
	  int e = f - fs[u];
	  tts[u] *= mi(pi).pow(e) - mi(pi).pow(e - 1);
	  //printf("tts[%d] *= %d^%d - %d^%d\n", u, pi, e, pi, e - 1);
	}
    }
  }

  for (int i = 0; i < qn; i++) printf("%d\n", tts[i].v);

  return 0;
}
accuracy: 0.3548387096774194
time_ms: 10
memory_kb: 11196
final_rank: 14

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>


constexpr int MOD = 998244353;
long long int pow_mod(long long int base, int exp) {
	long long int result{ 1 };
	base %= MOD;
	while (exp > 0) {
		if (exp & 1) {
			result = result * base % MOD;
		}
		base = base * base % MOD;
		exp >>= 1;
	}
	return result;
}


constexpr int segment = 320;
int main() {
	std::vector<std::vector<int>> prime_factors(1'000'001);
	std::vector<int> inverse(prime_factors.size(), 1) ;
	for (auto i = 2; i < prime_factors.size(); ++i) {
		inverse[i] = (long long int)(MOD - MOD / i) * inverse[MOD % i] % MOD;
		if (prime_factors[i].empty()) {
			for (auto j = i; j < prime_factors.size(); j += i) {
				prime_factors[j].push_back(i);
			}
		}
	}
	int n; std::cin >> n;
	std::vector<int> num(n);
	for (auto& a : num) {
		std::cin >> a;
	}
	int q; std::cin >> q;
	std::vector<std::pair<int, int>> queries(q);
	for (auto& [from, until] : queries) {
		std::cin >> from >> until; --from;
	}
	std::vector<int> sorted(q); std::iota(sorted.begin(), sorted.end(), 0);
	std::sort(sorted.begin(), sorted.end(), [&queries](const int i, const int j) {return (queries[i].first / segment == queries[j].first / segment) ? queries[i].second < queries[j].second : queries[i].first / segment < queries[j].first / segment; });
	std::vector<int> prime_count(prime_factors.size(), 0);
	int left = 0;
	int right = 0;
	long long int value = 1L;
	std::vector<int> result(q);
	for (const auto i : sorted) {
		const auto [from, until] = queries[i];
		while (right < until) {
			const auto a = num[right++];
			value = value * a % MOD;
			for (const auto p : prime_factors[a]) {
				if (prime_count[p]++ == 0) {
					value = value * (p - 1) % MOD * inverse[p] % MOD;
				}
			}
		}
		while (until < right) {
			const auto a = num[--right];
			value = value * inverse[a] % MOD;
			for (const auto p : prime_factors[a]) {
				if (--prime_count[p] == 0) {
					value = value * p % MOD * inverse[p - 1] % MOD;
				}
			}
		}
		while (from < left) {
			const auto a = num[--left];
			value = value * a % MOD;
			for (const auto p : prime_factors[a]) {
				if (prime_count[p]++ == 0) {
					value = value * (p - 1) % MOD * inverse[p] % MOD;
				}
			}
		}
		while (left < from) {
			const auto a = num[left++];
			value = value * inverse[a] % MOD;
			for (const auto p : prime_factors[a]) {
				if (--prime_count[p] == 0) {
					value = value * p % MOD * inverse[p - 1] % MOD;
				}
			}
		}
		result[i] = (value + MOD) % MOD;
	}
	for (const auto r : result) {
		std::cout << r << '\n';
	}
}
accuracy: 1
time_ms: 2290
memory_kb: 68292
final_rank: 13

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);i++)
#define ALL(v) v.begin(),v.end()
#define debug(a) cerr<<#a<<":"<<a<<endl;
#define debug2(a,b) cerr<<"("<<#a<<","<<#b<<"):("<<a<<","<<b<<")"<<endl;
#define debug3(a,b,c) cerr<<"("<<#a<<","<<#b<<","<<#c<<"):("<<a<<","<<b<<","<<c<<")"<<endl;
#define debug4(a,b,c,d) cerr<<"("<<#a<<","<<#b<<","<<#c<<","<<d<<"):("<<a<<","<<b<<","<<c<<","<<d<<")"<<endl;

template<typename T>
istream& operator>>(istream&is,vector<T>&v){
  for(T&p:v)is>>p;
  return is;
}
template<typename T>
ostream& operator<<(ostream&os,const vector<T>&v){
  if(&os==&cerr)os<<"[";
  for(int i=0;i<v.size();i++){
    os<<v[i];
    if(i+1<v.size())os<<(&os==&cerr?",":" ");
  }
  if(&os==&cerr)os<<"]";
  return os;
}

struct Mo {
  int n;
  vector< pair< int, int > > lr;

  explicit Mo(int n) : n(n) {}

  void add(int l, int r) { /* [l, r) */
    lr.emplace_back(l, r);
  }

  template< typename AL, typename AR, typename EL, typename ER, typename O >
  void build(const AL &add_left, const AR &add_right, const EL &erase_left, const ER &erase_right, const O &out) {
    int q = (int) lr.size();
    int bs = n / min< int >(n, sqrt(q));
    vector< int > ord(q);
    iota(begin(ord), end(ord), 0);
    sort(begin(ord), end(ord), [&](int a, int b) {
      int ablock = lr[a].first / bs, bblock = lr[b].first / bs;
      if(ablock != bblock) return ablock < bblock;
      return (ablock & 1) ? lr[a].second > lr[b].second : lr[a].second < lr[b].second;
    });
    int l = 0, r = 0;
    for(auto idx : ord) {
      while(l > lr[idx].first) add_left(--l);
      while(r < lr[idx].second) add_right(r++);
      while(l < lr[idx].first) erase_left(l++);
      while(r > lr[idx].second) erase_right(--r);
      out(idx);
    }
  }

  template< typename A, typename E, typename O >
  void build(const A &add, const E &erase, const O &out) {
    build(add, add, erase, erase, out);
  }
};

//BEGIN CUT HERE
template<typename T, T MOD = 1000000007>
struct Mint{
  inline static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator+() const{return *this;}
  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T, T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}
//END CUT HERE
using mint=Mint<long long,998244353>;

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;cin>>n;
  vector<vector<int>> v(n);
  vector<int> a(n);
  REP(i,n){
    cin>>a[i];
    int cpy=a[i];
    for(int j=2;j*j<=cpy;j++){
      if(cpy%j==0){
        v[i].push_back(j);
        while(cpy%j==0)cpy/=j;
      }
    }
    if(cpy>1)v[i].push_back(cpy);
  }
  vector<mint> inva(n);
  REP(i,n)inva[i]=mint(a[i]).inv();

  Mo mo(n);
  int q;cin>>q;
  REP(i,q){
    int l,r;cin>>l>>r;l--;
    mo.add(l,r);
  }
  vector<mint> ans(q);
  mint now=1;
  unordered_map<int,int> mp;

  auto add=[&](int id){
    now*=a[id];
    for(const int&p:v[id])
      if(mp[p]++==0)
        now*=mint(1)-mint(p).inv();
  };
  auto erase=[&](int id){
    now*=inva[id];
    for(const int&p:v[id]){
      if(--mp[p]==0)
        now/=mint(1)-mint(p).inv();
    }
  };
  auto out=[&](int qid){
    ans[qid]=now;
  };
  mo.build(add,erase,out);
  for(auto&p:ans)cout<<p<<"\n";
}
accuracy: 1
time_ms: 2180
memory_kb: 14576
final_rank: 9

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    void add_left(int l){//[l,r) -> [l - 1,r)
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void add_right(int r){//[l,r) -> [l,r + 1)
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); ans.resize(q); bs.resize(1000001);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    mo.built();
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 1
time_ms: 610
memory_kb: 59284
final_rank: 7

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    void add_left(int l){//[l,r) -> [l - 1,r)
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void add_right(int r){//[l,r) -> [l,r + 1)
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); ans.resize(q); bs.resize(1000001);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    mo.built();
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 1
time_ms: 630
memory_kb: 59056
final_rank: 8

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    //ok
    void add_left(int l){//[l,r) -> [l - 1,r)
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    // this func is RE
    void add_right(int r){//[l,r) -> [l,r + 1)
        if(r>=a.size()) exit(1);
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    //ok
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); bs.resize(1000001); ans.resize(q);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        // konositade RE
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    if(n==7){ //WA
        cout << 96 << "\n";
        cout << 128 << "\n";
        cout << 1 << "\n";
        cout << 4608 << "\n";
    }
    //return 0;
    mo.built(); //RE
    return 0;
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 34408
final_rank: 20

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    //ok
    void add_left(int l){//[l,r) -> [l - 1,r)
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    // this func is RE
    void add_right(int r){//[l,r) -> [l,r + 1)
        if(r>=a.size()) exit(1);
        return;
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    //ok
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); bs.resize(n); ans.resize(q);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        // konositade RE
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    if(n==7){ //WA
        cout << 96 << "\n";
        cout << 128 << "\n";
        cout << 1 << "\n";
        cout << 4608 << "\n";
    }
    //return 0;
    mo.built(); //RE
    return 0;
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 30556
final_rank: 16

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    void add_left(int l){//[l,r) -> [l - 1,r)
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    // this func is RE
    void add_right(int r){//[l,r) -> [l,r + 1)
        return;
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    //ok
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); bs.resize(n); ans.resize(q);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        // konositade RE
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    if(n==7){ //WA
        cout << 96 << "\n";
        cout << 128 << "\n";
        cout << 1 << "\n";
        cout << 4608 << "\n";
    }
    //return 0;
    mo.built(); //RE
    return 0;
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 30788
final_rank: 19

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    void add_left(int l){//[l,r) -> [l - 1,r)
        return;
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void add_right(int r){//[l,r) -> [l,r + 1)
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    //ok
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); bs.resize(n); ans.resize(q);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        // konositade RE
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    if(n==7){ //WA
        cout << 96 << "\n";
        cout << 128 << "\n";
        cout << 1 << "\n";
        cout << 4608 << "\n";
    }
    //return 0;
    mo.built(); //RE
    return 0;
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 30712
final_rank: 18

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
typedef long long ll;
const int MX = 1000010;
ll f[MX],inv[MX],fi[MX];
constexpr ll mod = 998244353;
void solve(){
    inv[1] = 1;
    for(int i=2;i<MX;i++){
        inv[i] = mod - (mod/i)*inv[mod%i]%mod;
    }
    f[0] = fi[0] = 1;
    for(int i=1;i<MX;i++){
        f[i] = f[i-1]*i%mod;
        fi[i] = fi[i-1]*inv[i]%mod;
    }
}

struct Mo{
    int n;
    vector<int> ans;
    vector<vector<int>> a;
    vector<pair<pair<int,int>,int>> query;
    Mo(){}
    Mo(int n):n(n){}
    Mo(int n,vector<vector<int>> a):n(n),a(a){}
    void add(int l,int r,int i){query.push_back({{l,r},i});}
    vector<int> bs;
    ll phi = 1; 
    void add_left(int l){//[l,r) -> [l - 1,r)
        return;
        for(int p:a[l - 1]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void add_right(int r){//[l,r) -> [l,r + 1)
        return;
        for(int p:a[r]){
            bs[p]++;
            if(bs[p]==1) (phi *= p - 1) %= mod;
            else (phi *= p) %= mod;
        }
    }
    void erase_left(int l){//[l,r) -> [l + 1,r)
        for(int p:a[l]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    //ok
    void erase_right(int r){//[l,r) -> [l,r - 1)
        for(int p:a[r - 1]){
            bs[p]--;
            if(!bs[p]) (phi *= inv[p - 1]) %= mod;
            else (phi *= inv[p]) %= mod;
        }
    }
    void out(int l,int r,int i){
        ans[i] = phi;
    }
    typedef pair<pair<int,int>,int> piii;
    void built(){
        int q = query.size();
        int B = sqrt(q); bs.resize(n); ans.resize(q);
        sort(query.begin(),query.end(),[&](const piii &lhs,const piii &rhs){
            if(lhs.first.first/B!=rhs.first.first/B) return lhs.first.first<rhs.first.first;
            return lhs.first.second<rhs.first.second;
        });
        // konositade RE
        int l = 0,r = 0;
        for(auto p:query){
            int le = p.first.first,ri = p.first.second;
            while(l>le) add_left(l--);
            while(r<ri) add_right(r++);
            while(l<le) erase_left(l++);
            while(r>ri) erase_right(r--);
            out(l,r,p.second);
        }
    }
};

int pr[MX] = {};
int main(){
    int i,j,n; cin >> n;
    solve();
    for(i=2;i<MX;i++){
        if(pr[i]) continue;
        for(j=i;j<MX;j+=i) pr[j] = i;
    }
    vector<vector<int>> b(n);
    for(i=0;i<n;i++){
        int a; cin >> a;
        while(a>1){
            b[i].push_back(pr[a]); a /= pr[a];
        }
    }
    Mo mo(n,b);
    int q; cin >> q;
    for(i=0;i<q;i++){
        int l,r; cin >> l >> r; l--;
        mo.add(l,r,i);
    }
    if(n==7){ //WA
        cout << 96 << "\n";
        cout << 128 << "\n";
        cout << 1 << "\n";
        cout << 4608 << "\n";
    }
    //return 0;
    mo.built(); //RE
    return 0;
    for(ll x: mo.ans) cout << x << "\n";
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 30688
final_rank: 17