题意:
解法:
如果问题可以离线,那么莫队可以直接冲过去,可惜离不得。
每个数最多只有一个>sqrt的质因子,sqrt(2e5)<90,
开90棵线段树分别维护前90个质因子的区间最大指数。
去掉前90个质因子后,每个数只剩下1或者一个>sqrt(a(i))的质因子,指数都为1,
那么问题变为求区间乘积,且相同的数只计算一次贡献,可以用可持久化线段树做。
ps:
代码TLE了,但是在pushup前面加了一个inline就过了(少调用了几次函数),hhh。
这题改成ST表应该能跑的快一点。
质因子的题可以考虑将<sq和>sq的可以分开计算。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
const int mod=1e9+7;
int prime[maxm],cnt;
int mark[maxm];
int b[maxm];
int n;
int last;
struct Tree{
int a[maxm<<2];
inline void pp(int node){
a[node]=max(a[node*2],a[node*2+1]);
}
void build(int l,int r,int node,int k){
if(l==r){
while(b[l]%k==0){
a[node]++;
b[l]/=k;
}
return ;
}
int mid=(l+r)/2;
build(l,mid,node*2,k);
build(mid+1,r,node*2+1,k);
pp(node);
}
int ask(int st,int ed,int l,int r,int node){
if(st<=l&&ed>=r)return a[node];
int mid=(l+r)/2;
int ans=0;
if(st<=mid)ans=max(ans,ask(st,ed,l,mid,node*2));
if(ed>mid)ans=max(ans,ask(st,ed,mid+1,r,node*2+1));
return ans;
}
}T[100];
struct Tree2{
int lc[maxm*20],rc[maxm*20],mul[maxm*20];
int rt[maxm],tot;
inline void pp(int k){
mul[k]=1ll*mul[lc[k]]*mul[rc[k]]%mod;
}
void update(int x,int val,int l,int r,int &k,int last){
k=++tot;
lc[k]=lc[last];
rc[k]=rc[last];
if(l==r){
mul[k]=val;
return ;
}
int mid=(l+r)/2;
if(x<=mid)update(x,val,l,mid,lc[k],lc[last]);
else update(x,val,mid+1,r,rc[k],rc[last]);
pp(k);
}
int ask(int st,int ed,int l,int r,int k){
if(mul[k]<=1)return 1;
if(st<=l&&ed>=r)return mul[k];
int mid=(l+r)/2;
int ans=1;
if(st<=mid)ans=1ll*ans*ask(st,ed,l,mid,lc[k])%mod;
if(ed>mid)ans=1ll*ans*ask(st,ed,mid+1,r,rc[k])%mod;
return ans;
}
}TT;
bool isprime(int x){
for(int i=2;i*i<=x;i++){
if(x%i==0)return 0;
}
return 1;
}
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return ans;
}
signed main(){
//
TT.mul[0]=1;
const int sq=sqrt(2e5);
for(int i=2;i<=sq;i++){
if(isprime(i)){
prime[cnt++]=i;
}
}
//
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
for(int i=0;i<cnt;i++){
T[i].build(1,n,1,prime[i]);
}
for(int i=1;i<=n;i++){
if(b[i]==1){
TT.rt[i]=TT.rt[i-1];
}else{
if(mark[b[i]]){
TT.update(mark[b[i]],1,1,n,TT.rt[i],TT.rt[i-1]);
TT.update(i,b[i],1,n,TT.rt[i],TT.rt[i]);
}else{
TT.update(i,b[i],1,n,TT.rt[i],TT.rt[i-1]);
}
mark[b[i]]=i;
}
}
//
int q;scanf("%d",&q);
while(q--){
int x,y;scanf("%d%d",&x,&y);
int l=(x+last)%n+1,r=(y+last)%n+1;
if(l>r)swap(l,r);
int ans=TT.ask(l,r,1,n,TT.rt[r]);
for(int i=0;i<cnt;i++){
int cnt=T[i].ask(l,r,1,n,1);
if(cnt){
ans=1ll*ans*ppow(prime[i],cnt,mod)%mod;
}
}
printf("%d\n",ans);
last=ans;
}
return 0;
}