#include <cstdio>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 100,mod = 1e9 + 7;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int base,int b){
    int res = 1;
    while(b){
        if(b & 1)res = mul(res,base);
        base = mul(base,base);
        b >>= 1;
    }
    return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
inline int mdiv(int a,int b){return mul(a,inv(b));}
int vis[maxn],rnk[maxn];
vector<int> pri;
inline void sieve(){
    vis[1] = 1;
    for(int i = 2;i < maxn;i++){
        if(!vis[i])pri.push_back(i),rnk[i] = pri.size();
        for(int x : pri){
            if(1ll * x * i >= maxn)break;
            vis[x * i] = 1;
            if (i % x == 0)break;
        }
    }
}
int n,m,siz,val[maxn],last[maxn];
struct tree{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    int tr[maxn << 2];
    inline void pushup(int rt){tr[rt] = max(tr[ls],tr[rs]);}
    inline void modify(int pos,int v,int l = 1,int r = n,int rt = 1){
        if(l == r){
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,l,mid,ls);
        else modify(pos,v,mid + 1,r,rs);
        pushup(rt);
    }
    inline int query(int a,int b,int l = 1,int r = n,int rt = 1){
        if(a <= l && b >= r)return tr[rt];
        int res = -0x7fffffff,mid = (l + r) >> 1;
        if(a <= mid)res = max(res,query(a,b,l,mid,ls));
        if(b >= mid + 1)res = max(res,query(a,b,mid + 1,r,rs));
        return res;
    }
    #undef ls
    #undef rs
}seg[100];
namespace st{
    struct node{int ls,rs,v = 1;}tr[maxn * 32];
    int rt[maxn],tot;
    inline void pushup(int rt){tr[rt].v = mul(tr[tr[rt].ls].v,tr[tr[rt].rs].v);}
    inline void modify(int pos,int v,int &rt,int last,int l = 0,int r = n){
        rt = ++tot;
        if(l == r){
            tr[rt].v = mul(tr[last].v,v);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,tr[rt].ls,tr[last].ls,l,mid),tr[rt].rs = tr[last].rs;
        else modify(pos,v,tr[rt].rs,tr[last].rs,mid + 1,r),tr[rt].ls = tr[last].ls;
        pushup(rt);
    }
    inline int query(int a,int b,int rt,int l = 0,int r = n){
        if(a <= l && b >= r)return tr[rt].v;
        int res = 1,mid = (l + r) >> 1;
        if(a <= mid)res = mul(res,query(a,b,tr[rt].ls,l,mid));
        if(b >= mid + 1)res = mul(res,query(a,b,tr[rt].rs,mid + 1,r));
        return res;
    }
}
int main(){
    // freopen("fafa.in","r",stdin);
    sieve();
    n = read(),siz = 500;
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int i = 1;i <= n;i++){
        int now = val[i],flg = 0;
        // printf("%d: ",now);
        for(int x : pri){
            if(now == 1)break;
            if(now % x)continue;
            int p = 0;
            while(now % x == 0)now /= x,p++;
            // printf("(%d,%d) ",x,p);
            if(x <= siz)seg[rnk[x]].modify(i,p);
            else{
                st::modify(last[x],x,st::rt[i],st::rt[i - 1]);
                flg = 1;
                last[x] = i;
            }
        }
        // printf("\n");
        if(!flg)st::rt[i] = st::rt[i - 1];
    }
    int q = read(),lastans = 0;
    while(q--){
        int l = (lastans + read()) % n + 1,r = (lastans + read()) % n + 1,ans = 1;
        if(l > r)swap(l,r);
        for(int i = 1;i < 100;i++)ans = mul(ans,qpow(pri[i - 1],seg[i].query(l,r)));
        ans = mul(ans,mdiv(st::query(0,l - 1,st::rt[r]),st::query(0,l - 1,st::rt[l - 1])));
        printf("%d\n",lastans = ans);
    }
    return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 100,mod = 1e9 + 7;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int base,int b){
    int res = 1;
    while(b){
        if(b & 1)res = mul(res,base);
        base = mul(base,base);
        b >>= 1;
    }
    return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
inline int mdiv(int a,int b){return mul(a,inv(b));}
int vis[maxn],rnk[maxn];
vector<int> pri;
inline void sieve(){
    vis[1] = 1;
    for(int i = 2;i < maxn;i++){
        if(!vis[i])pri.push_back(i),rnk[i] = pri.size();
        for(int x : pri){
            if(1ll * x * i >= maxn)break;
            vis[x * i] = 1;
            if (i % x == 0)break;
        }
    }
}
int n,m,siz,val[maxn],last[maxn];
struct tree{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    int tr[maxn << 2];
    inline void pushup(int rt){tr[rt] = max(tr[ls],tr[rs]);}
    inline void modify(int pos,int v,int l = 1,int r = n,int rt = 1){
        if(l == r){
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,l,mid,ls);
        else modify(pos,v,mid + 1,r,rs);
        pushup(rt);
    }
    inline int query(int a,int b,int l = 1,int r = n,int rt = 1){
        if(a <= l && b >= r)return tr[rt];
        int res = -0x7fffffff,mid = (l + r) >> 1;
        if(a <= mid)res = max(res,query(a,b,l,mid,ls));
        if(b >= mid + 1)res = max(res,query(a,b,mid + 1,r,rs));
        return res;
    }
    #undef ls
    #undef rs
}seg[100];
namespace st{
    struct node{int ls,rs,v = 1;}tr[maxn * 32];
    int rt[maxn],tot;
    inline void pushup(int rt){tr[rt].v = mul(tr[tr[rt].ls].v,tr[tr[rt].rs].v);}
    inline void modify(int pos,int v,int &rt,int last,int l = 0,int r = n){
        rt = ++tot;
        if(l == r){
            tr[rt].v = mul(tr[last].v,v);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,tr[rt].ls,tr[last].ls,l,mid),tr[rt].rs = tr[last].rs;
        else modify(pos,v,tr[rt].rs,tr[last].rs,mid + 1,r),tr[rt].ls = tr[last].ls;
        pushup(rt);
    }
    inline int query(int a,int b,int rt,int l = 0,int r = n){
        if(a <= l && b >= r)return tr[rt].v;
        int res = 1,mid = (l + r) >> 1;
        if(a <= mid)res = mul(res,query(a,b,tr[rt].ls,l,mid));
        if(b >= mid + 1)res = mul(res,query(a,b,tr[rt].rs,mid + 1,r));
        return res;
    }
}
int main(){
    // freopen("fafa.in","r",stdin);
    sieve();
    n = read(),siz = 500;
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int i = 1;i <= n;i++){
        int now = val[i],flg = 0;
        // printf("%d: ",now);
        for(int x : pri){
            if(now == 1)break;
            if(now % x)continue;
            int p = 0;
            while(now % x == 0)now /= x,p++;
            // printf("(%d,%d) ",x,p);
            if(x <= siz)seg[rnk[x]].modify(i,p);
            else{
                st::modify(last[x],x,st::rt[i],st::rt[i - 1]);
                flg = 1;
                last[x] = i;
            }
        }
        printf("\n");
        if(!flg)st::rt[i] = st::rt[i - 1];
    }
    int q = read(),lastans = 0;
    while(q--){
        int l = (lastans + read()) % n + 1,r = (lastans + read()) % n + 1,ans = 1;
        if(l > r)swap(l,r);
        for(int i = 1;i < 100;i++)ans = mul(ans,qpow(pri[i - 1],seg[i].query(l,r)));
        ans = mul(ans,mdiv(st::query(0,l - 1,st::rt[r]),st::query(0,l - 1,st::rt[l - 1])));
        printf("%d\n",lastans = ans);
    }
    return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 100,mod = 1e9 + 7;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int base,int b){
    int res = 1;
    while(b){
        if(b & 1)res = mul(res,base);
        base = mul(base,base);
        b >>= 1;
    }
    return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
inline int mdiv(int a,int b){return mul(a,inv(b));}
int vis[maxn],rnk[maxn];
vector<int> pri;
inline void sieve(){
    vis[1] = 1;
    for(int i = 2;i < maxn;i++){
        if(!vis[i])pri.push_back(i),rnk[i] = pri.size();
        for(int x : pri){
            if(1ll * x * i >= maxn)break;
            vis[x * i] = 1;
            if (i % x == 0)break;
        }
    }
}
int n,m,siz,val[maxn],last[maxn];
struct tree{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    unsigned char tr[maxn << 2];
    inline void pushup(int rt){tr[rt] = max(tr[ls],tr[rs]);}
    inline void modify(int pos,int v,int l = 1,int r = n,int rt = 1){
        if(l == r){
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,l,mid,ls);
        else modify(pos,v,mid + 1,r,rs);
        pushup(rt);
    }
    inline unsigned char query(int a,int b,int l = 1,int r = n,int rt = 1){
        if(tr[rt] == 0)return 0;
        if(a <= l && b >= r)return tr[rt];
        unsigned char res = 0;
        int mid = (l + r) >> 1;
        if(a <= mid)res = max(res,query(a,b,l,mid,ls));
        if(b >= mid + 1)res = max(res,query(a,b,mid + 1,r,rs));
        return res;
    }
    #undef ls
    #undef rs
}seg[100];
namespace st{
    struct node{int ls,rs,v = 1;}tr[maxn * 20];
    int rt[maxn],tot;
    inline void pushup(int rt){tr[rt].v = mul(tr[tr[rt].ls].v,tr[tr[rt].rs].v);}
    inline void modify(int pos,int v,int &rt,int last,int l = 0,int r = n){
        rt = ++tot;
        if(l == r){
            tr[rt].v = mul(tr[last].v,v);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,tr[rt].ls,tr[last].ls,l,mid),tr[rt].rs = tr[last].rs;
        else modify(pos,v,tr[rt].rs,tr[last].rs,mid + 1,r),tr[rt].ls = tr[last].ls;
        pushup(rt);
    }
    inline int query(int a,int b,int rt,int l = 0,int r = n){
        if(tr[rt].v == 1)return 1;
        if(a <= l && b >= r)return tr[rt].v;
        int res = 1,mid = (l + r) >> 1;
        if(a <= mid)res = mul(res,query(a,b,tr[rt].ls,l,mid));
        if(b >= mid + 1)res = mul(res,query(a,b,tr[rt].rs,mid + 1,r));
        return res;
    }
}
int main(){
    sieve();
    n = read(),siz = 500;
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int i = 1;i <= n;i++){
        int now = val[i],flg = 0;
        for(int x : pri){
            if(now == 1)break;
            if(now % x)continue;
            int p = 0;
            while(now % x == 0)now /= x,p++;
            if(x <= siz)seg[rnk[x]].modify(i,p);
            else{
                st::modify(last[x],x,st::rt[i],st::rt[i - 1]);
                flg = 1;
                last[x] = i;
            }
        }
        if(!flg)st::rt[i] = st::rt[i - 1];
    }
    int q = read(),lastans = 0;
    while(q--){
        int l = (lastans + read()) % n + 1,r = (lastans + read()) % n + 1,ans = 1;
        if(l > r)swap(l,r);
        for(int i = 1;i < 100;i++)ans = mul(ans,qpow(pri[i - 1],seg[i].query(l,r)));
        ans = mul(ans,mdiv(st::query(0,l - 1,st::rt[r]),st::query(0,l - 1,st::rt[l - 1])));
        printf("%d\n",lastans = ans);
    }
    return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 100,mod = 1e9 + 7;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int base,int b){
    int res = 1;
    while(b){
        if(b & 1)res = mul(res,base);
        base = mul(base,base);
        b >>= 1;
    }
    return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
inline int mdiv(int a,int b){return mul(a,inv(b));}
int vis[maxn],rnk[maxn];
vector<int> pri;
inline void sieve(){
    vis[1] = 1;
    for(int i = 2;i < maxn;i++){
        if(!vis[i])pri.push_back(i),rnk[i] = pri.size();
        for(int x : pri){
            if(1ll * x * i >= maxn)break;
            vis[x * i] = 1;
            if (i % x == 0)break;
        }
    }
}
int n,m,siz,val[maxn],last[maxn];
struct tree{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    unsigned char tr[maxn << 2];
    inline void pushup(int rt){tr[rt] = max(tr[ls],tr[rs]);}
    inline void modify(int pos,int v,int l = 1,int r = n,int rt = 1){
        if(l == r){
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,l,mid,ls);
        else modify(pos,v,mid + 1,r,rs);
        pushup(rt);
    }
    inline unsigned char query(int a,int b,int l = 1,int r = n,int rt = 1){
        if(a <= l && b >= r)return tr[rt];
        unsigned char res = 0;
        int mid = (l + r) >> 1;
        if(a <= mid)res = max(res,query(a,b,l,mid,ls));
        if(b >= mid + 1)res = max(res,query(a,b,mid + 1,r,rs));
        return res;
    }
    #undef ls
    #undef rs
}seg[100];
namespace st{
    struct node{int ls,rs,v = 1;}tr[maxn * 20];
    int rt[maxn],tot;
    inline void pushup(int rt){tr[rt].v = mul(tr[tr[rt].ls].v,tr[tr[rt].rs].v);}
    inline void modify(int pos,int v,int &rt,int last,int l = 0,int r = n){
        rt = ++tot;
        if(l == r){
            tr[rt].v = mul(tr[last].v,v);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,tr[rt].ls,tr[last].ls,l,mid),tr[rt].rs = tr[last].rs;
        else modify(pos,v,tr[rt].rs,tr[last].rs,mid + 1,r),tr[rt].ls = tr[last].ls;
        pushup(rt);
    }
    inline int query(int a,int b,int rt,int l = 0,int r = n){
        if(a <= l && b >= r)return tr[rt].v;
        int res = 1,mid = (l + r) >> 1;
        if(a <= mid)res = mul(res,query(a,b,tr[rt].ls,l,mid));
        if(b >= mid + 1)res = mul(res,query(a,b,tr[rt].rs,mid + 1,r));
        return res;
    }
}
int main(){
    sieve();
    n = read(),siz = 500;
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int i = 1;i <= n;i++){
        int now = val[i],flg = 0;
        for(int x : pri){
            if(now == 1)break;
            if(now % x)continue;
            int p = 0;
            while(now % x == 0)now /= x,p++;
            if(x <= siz)seg[rnk[x]].modify(i,p);
            else{
                st::modify(last[x],x,st::rt[i],st::rt[i - 1]);
                flg = 1;
                last[x] = i;
            }
        }
        if(!flg)st::rt[i] = st::rt[i - 1];
    }
    int q = read(),lastans = 0;
    while(q--){
        int l = (lastans + read()) % n + 1,r = (lastans + read()) % n + 1,ans = 1;
        if(l > r)swap(l,r);
        for(int i = 1;i < 100;i++)ans = mul(ans,qpow(pri[i - 1],seg[i].query(l,r)));
        ans = mul(ans,mdiv(st::query(0,l - 1,st::rt[r]),st::query(0,l - 1,st::rt[l - 1])));
        printf("%d\n",lastans = ans);
    }
    return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
#pragma GCC optmize(3)
using namespace std;
const int maxn = 2e5 + 100,mod = 1e9 + 7;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int base,int b){
    int res = 1;
    while(b){
        if(b & 1)res = mul(res,base);
        base = mul(base,base);
        b >>= 1;
    }
    return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
inline int mdiv(int a,int b){return mul(a,inv(b));}
int vis[maxn],rnk[maxn],mf[maxn];
vector<int> pri;
inline void sieve(){
    vis[1] = 1;
    for(int i = 2;i < maxn;i++){
        if(!vis[i])mf[i] = i,pri.push_back(i),rnk[i] = pri.size();
        for(int x : pri){
            if(1ll * x * i >= maxn)break;
            vis[x * i] = 1;
            mf[x * i] = x;
            if (i % x == 0)break;
        }
    }
}
int n,m,siz,val[maxn],last[maxn];
struct tree{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    unsigned char tr[int(1e5 + 1) << 2];
    inline void pushup(int rt){tr[rt] = max(tr[ls],tr[rs]);}
    inline void modify(int pos,int v,int l = 1,int r = n,int rt = 1){
        if(l == r){
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,l,mid,ls);
        else modify(pos,v,mid + 1,r,rs);
        pushup(rt);
    }
    inline unsigned char query(int a,int b,int l = 1,int r = n,int rt = 1){
        if(tr[rt] == 0)return 0;
        if(a <= l && b >= r)return tr[rt];
        unsigned char res = 0;
        int mid = (l + r) >> 1;
        if(a <= mid)res = max(res,query(a,b,l,mid,ls));
        if(b >= mid + 1)res = max(res,query(a,b,mid + 1,r,rs));
        return res;
    }
    #undef ls
    #undef rs
}seg[100];
namespace st{
    struct node{int ls,rs,v;}tr[maxn * 20];
    int rt[maxn],tot;
    inline void build(int &rt,int l = 0,int r = n){
		rt = ++tot;
		tr[rt].v = 1;
		if(l == r)return;
		int mid = (l + r) >> 1;
		build(tr[rt].ls,l,mid);
		build(tr[rt].rs,mid + 1,r);
	}
    inline void pushup(int rt){tr[rt].v = mul(tr[tr[rt].ls].v,tr[tr[rt].rs].v);}
    inline void modify(int pos,int v,int &rt,int last,int l = 0,int r = n){
        rt = ++tot;
        if(l == r){
            tr[rt].v = mul(tr[last].v,v);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(pos,v,tr[rt].ls,tr[last].ls,l,mid),tr[rt].rs = tr[last].rs;
        else modify(pos,v,tr[rt].rs,tr[last].rs,mid + 1,r),tr[rt].ls = tr[last].ls;
        pushup(rt);
    }
    inline int query(int a,int b,int rt,int l = 0,int r = n){
        if(tr[rt].v == 1)return 1;
        if(a <= l && b >= r)return tr[rt].v;
        int res = 1,mid = (l + r) >> 1;
        if(a <= mid)res = mul(res,query(a,b,tr[rt].ls,l,mid));
        if(b >= mid + 1)res = mul(res,query(a,b,tr[rt].rs,mid + 1,r));
        return res;
    }
}
int main(){
    sieve();
    n = read(),siz = 500;
	st::build(st::rt[0]);
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int i = 1;i <= n;i++){
        int now = val[i],flg = 0;
        while(now != 1){
            int x = mf[now],p = 0;
            while(now % x == 0)now /= x,p++;
            if(x <= siz)seg[rnk[x]].modify(i,p);
            else{
                st::modify(last[x],x,st::rt[i],st::rt[i - 1]);
                flg = 1;
                last[x] = i;
            }
        }
        if(!flg)st::rt[i] = st::rt[i - 1];
    }
    int q = read(),lastans = 0;
    while(q--){
        int l = (lastans + read()) % n + 1,r = (lastans + read()) % n + 1,ans = 1;
        if(l > r)swap(l,r);
        for(int i = 1;i < 100;i++)ans = mul(ans,qpow(pri[i - 1],seg[i].query(l,r)));
        ans = mul(ans,mdiv(st::query(0,l - 1,st::rt[r]),st::query(0,l - 1,st::rt[l - 1])));
        printf("%d\n",lastans = ans);
    }
    return 0;
}


#include <bits/stdc++.h>

const int N = 100003;
const int M = 200007;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int m;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    Build(1, n, root[0]);
  }

  // 第cur棵树等于第last棵树，即在cur位置没有更新
  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 第id个位置直接修改为x，得到编号为cur的新树
  void ChangeSingle(int cur, int id, long long x) {
    ChangeSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 第id个位置在原来数字的基础上乘以x，得到编号为cur的新树
  void IncreaseSingle(int cur, int id, long long x) {
    IncreaseSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树，区间乘积初始化为1
  void Build(int l, int r, int& rt) {
    rt = ++cnt;
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点为rt_old的树的id位置改成x
  // 相当于在根节点为rt_old的旧树的基础上新添logn个节点，得到根为rt的新树
  void ChangeSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ChangeSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      ChangeSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // rt_old为根的树的id位置乘以x
  void IncreaseSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = (pro[rt_old] * x) % mod;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      IncreaseSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      IncreaseSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // 询问根节点为rt的树在[L,R]区间内的乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  void Up(int rt) {
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 380];        // 节点的左儿子编号
  int rs[N * 380];        // 节点的右儿子编号
  long long pro[N * 380]; // 节点所表征区间的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Factorization {

public:
  Factorization() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        pri[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }
  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void Factorize(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && pri[i] <= sn; ++i) {
      if (n % pri[i] == 0) {
        PrimeFactor p(pri[i], 0);
        while (n % pri[i] == 0) {
          ++p.num;
          n /= pri[i];
        }
        vec.emplace_back(p);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
    }
  }

private:
  bool vis[M];        // i是否为质数
  long long pri[M];   // 质数集合，从小到大排列
  int cnt;            // 质数个数

}prime_fac; // class Factorization

class NumberPreprocess {

public:
  NumberPreprocess() {}

  void PreInverseElement(int n) {
    inv[1] = 1ll;
    for(int i = 2; i <= n; ++i) {
      inv[i] = ((mod - mod / i) * inv[mod % i]) % mod;
    }
  }

  long long Inv(int i) {
    return inv[i];
  }

private:
  long long inv[M];

}np; // class NumberPreprocess

int n, q;
long long a[N];
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

int main() {

  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  prime_fac.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    prime_fac.Factorize(a[i], fac_pri[i]);
  }

  np.PreInverseElement(200000);
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    pers.Copy(i, i - 1);
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int number = fac_pri[i][j].num;
      long long tmp = 1ll;  // 记录pri的k次幂
      for (int k = 1; k <= number; ++k) {
        tmp *= pri;
        if (last_id[tmp]) {
          pers.IncreaseSingle(i, last_id[tmp], np.Inv(pri));
        }
        last_id[tmp] = i;
      }
    }
    pers.IncreaseSingle(i, i, a[i]);
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = pers.QueryProInterval(x, y);
    printf("%lld\n", ans);
    last = ans % n;
  }

  return 0;
}


#include <bits/stdc++.h>

const int N = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = -INF;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[90]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    // assert(root[last] != 0);
    ++cnt;
    int root_cur = cnt;
    CreateSingleImp(1, n_, cnt, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 50];        // 节点的左儿子编号
  int rs[N * 50];        // 节点的右儿子编号
  long long pro[N * 50]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int> _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);
        // printf("[%lld, %da], ", p.prime, p.num);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
      // printf("[%lld, %db]", vec.back().prime, vec.back().num);
    }
    // printf("\n");
  }

private:
  bool vis[N];        // i是否为质数
  long long prime[N]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[N];

int main() {
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(1000, pri);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  // assert(m < 90);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        // assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    long long pri = fac_pri[i].back().prime;
    int id = disc.Id(pri);
    if (id == -1) {
      if (!last_id[pri]) {
        pers.CreateSingle(i, i - 1, i, pri);
      } else {
        // long long inv_p = Pow(pri, mod - 2ll);
        pers.CreateSingle(i, i - 1, last_id[pri], 1ll);
        pers.CreateSingle(i, i, i, pri);
      }
      last_id[pri] = i;
    } else {
      pers.Copy(i, i - 1);
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  return 0;
}


#include <bits/stdc++.h>

const int N = 100010;
const int M = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int m;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[90][N]) {
    if (l == r) {
      for (int i = 1; i <= m; ++i) {
        mx_[rt][i] = v[i][l];
      }
      // mx_[rt][num] = v[num][l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int num, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt][num] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, num, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, num, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  void MaxInterval(int l, int r, int rt, int L, int R, int* ans) {
    if (L <= l && r <= R) {
      for (int i = 1; i <= m; ++i) {
        ans[i] = std::max(ans[i], mx_[rt][i]);
      }
      return;
    }
    int m = (l + r) >> 1;
    if (L <= m) {
      MaxInterval(l, m, rt << 1, L, R, ans);
    }
    if (R > m) {
      MaxInterval(m + 1, r, rt << 1 | 1, L, R, ans);
    }
    return;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    for (int i = 1; i <= m; ++i) {
      mx_[rt][i] = std::max(mx_[rt << 1][i], mx_[rt << 1 | 1][i]);
    }
  }

  int n_;
  int mx_[N<<2|1][90];        // 区间最大值
}seg; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    assert(root[last] != 0);
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    assert(root[last] != 0);
    int root_cur = ++cnt;
    CreateSingleImp(1, n_, root_cur, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 150];        // 节点的左儿子编号
  int rs[N * 150];        // 节点的右儿子编号
  long long pro[N * 150]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);
        // printf("[%lld, %da], ", p.prime, p.num);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
      // printf("[%lld, %db]", vec.back().prime, vec.back().num);
    }
    // printf("\n");
  }

private:
  bool vis[M];        // i是否为质数
  long long prime[M]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

struct FunTime {
  std::string topic;
  double run_time;

  FunTime() {}
  FunTime(std::string a, double b) : topic(a), run_time(b) {}
};

class Timer {
 public:
  Timer () {
    each_.clear();
    sum_ = 0.0;
  }
  ~Timer() { }
  void Init() {
    each_.clear();
    sum_ = 0.0;
  }
  void Begin() {
    beg_ = std::chrono::system_clock::now();
    // gettimeofday(&beg2_, NULL);
  }
  void End(const std::string& s) {
    end_ = std::chrono::system_clock::now();
    std::chrono::duration<double> tim = end_ - beg_;
    each_[s] += tim.count() * 1000;
    sum_ += tim.count() * 1000;

    // gettimeofday(&end2_, NULL);
    // double t = (end2_.tv_sec - beg2_.tv_sec) * 1000.0 + (end2_.tv_usec - beg2_.tv_usec) / 1000.0;
    // each_[s] += t;
    // sum_ += t;
    // std::cout << s << " End\n";
  }
  void PrintStatistics(const std::string& s) {
    std::cout << s << " Time Statistics ======================\n";
    std::cout << "Sum Run Time: " << sum_ <<  "ms\n";
    fun_times_.clear();
    for (auto x : each_) {
      fun_times_.push_back(FunTime(x.first, x.second));
    }
    sort(fun_times_.begin(), fun_times_.end(), [](FunTime x, FunTime y){return x.run_time > y.run_time;});
    for (size_t i = 0; i < fun_times_.size(); ++i) {
      double percentage = fun_times_[i].run_time / sum_;
      std::cout << fun_times_[i].topic << ": " << fun_times_[i].run_time << "ms " << percentage * 100.0 << "\%" << std::endl;
    }
  }
  double SumTime() {
    return sum_;
  }
 private:
  std::chrono::time_point<std::chrono::system_clock> beg_;
  std::chrono::time_point<std::chrono::system_clock> end_;
  // timeval beg2_;
  // timeval end2_;
  std::map<std::string, double> each_;
  std::vector<FunTime> fun_times_;
  double sum_;
}timer; // class Timer

int n, q;
long long a[N];
int b[90][N];
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

// #define Data
// #define Code

int main() {
// #ifdef Data
//   freopen("f.txt", "w", stdout);
//   printf("%d\n", 100000);
//   for (int i = 1; i <= 100000; ++i) {
//     printf("%d ", rand() % 200000);
//   }
//   printf("\n1\n");
//   int x = rand() % 100000;
//   int y = rand() % 100000;
//   if (x > y) {
//     std::swap(x, y);
//   }
//   printf("%d %d\n", x, y);
// #endif

// #ifdef Code
  freopen("f.txt", "r", stdin);
  timer.Begin();
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
  }
  disc.Build();
  m = disc.Size();
  assert(m < 90);
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        b[id][i] = num;
        // assert(id >= 1 && id <= m);
        // seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }
  seg.Init(n);
  seg.Build(1, n, 1, b);
  timer.End("Segment Preparation");

  timer.Begin();
  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    if (!fac_pri[i].size()) {
      pers.Copy(i, i - 1);
    } else {
      long long pri = fac_pri[i].back().prime;
      int id = disc.Id(pri);
      if (id == -1) {
        if (!last_id[pri]) {
          pers.CreateSingle(i, i - 1, i, pri);
        } else {
          // long long inv_p = Pow(pri, mod - 2ll);
          pers.CreateSingle(i, i - 1, last_id[pri], 1ll);
          pers.CreateSingle(i, i, i, pri);
        }
        last_id[pri] = i;
      } else {
        pers.Copy(i, i - 1);
      }
    }
  }
  timer.End("Persistent Segment Tree Preparation");

  timer.Begin();
  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    int num[90];
    for (int j = 1; j <= m; ++j) {
      num[j] = 0;
    }
    seg.MaxInterval(1, n, 1, x, y, num);
    for (int j = 1; j <= m; ++j) {
      ans = (ans * Pow(disc.Val(j), num[j])) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  timer.End("Query");

  // timer.PrintStatistics("All");
// #endif
  return 0;
}


#include <bits/stdc++.h>

const int N = 100003;
const int M = 200007;
const int K = N * 350;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int m;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    Build(1, n, root[0]);
  }

  // 第cur棵树等于第last棵树，即在cur位置没有更新
  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 第id个位置直接修改为x，得到编号为cur的新树
  void ChangeSingle(int cur, int id, long long x) {
    ChangeSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 第id个位置在原来数字的基础上乘以x，得到编号为cur的新树
  void IncreaseSingle(int cur, int id, long long x) {
    IncreaseSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树，区间乘积初始化为1
  void Build(int l, int r, int& rt) {
    rt = ++cnt;
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点为rt_old的树的id位置改成x
  // 相当于在根节点为rt_old的旧树的基础上新添logn个节点，得到根为rt的新树
  void ChangeSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ChangeSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      ChangeSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // rt_old为根的树的id位置乘以x
  void IncreaseSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = (1ll * pro[rt_old] * x) % mod;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      IncreaseSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      IncreaseSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // 询问根节点为rt的树在[L,R]区间内的乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  void Up(int rt) {
    pro[rt] = (1ll * pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[K];        // 节点的左儿子编号
  int rs[K];        // 节点的右儿子编号
  int pro[K]; // 节点所表征区间的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Factorization {

public:
  Factorization() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        pri[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }
  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void Factorize(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && pri[i] <= sn; ++i) {
      if (n % pri[i] == 0) {
        PrimeFactor p(pri[i], 0);
        while (n % pri[i] == 0) {
          ++p.num;
          n /= pri[i];
        }
        vec.emplace_back(p);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
    }
  }

private:
  bool vis[M];        // i是否为质数
  long long pri[M];   // 质数集合，从小到大排列
  int cnt;            // 质数个数

}prime_fac; // class Factorization

class NumberPreprocess {

public:
  NumberPreprocess() {}

  void PreInverseElement(int n) {
    inv[1] = 1ll;
    for(int i = 2; i <= n; ++i) {
      inv[i] = ((mod - mod / i) * inv[mod % i]) % mod;
    }
  }

  long long Inv(int i) {
    return inv[i];
  }

private:
  long long inv[M];

}np; // class NumberPreprocess

int n, q;
long long a[N];
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

int main() {

  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  prime_fac.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    prime_fac.Factorize(a[i], fac_pri[i]);
  }

  np.PreInverseElement(200000);
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    pers.Copy(i, i - 1);
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int number = fac_pri[i][j].num;
      long long tmp = 1ll;  // 记录pri的k次幂
      for (int k = 1; k <= number; ++k) {
        tmp *= pri;
        if (last_id[tmp]) {
          pers.IncreaseSingle(i, last_id[tmp], np.Inv(pri));
        }
        last_id[tmp] = i;
      }
    }
    pers.IncreaseSingle(i, i, a[i]);
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = pers.QueryProInterval(x, y);
    printf("%lld\n", ans);
    last = ans % n;
  }

  return 0;
}


#include <bits/stdc++.h>

const int N = 100010;
const int M = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = 0;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[90]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    assert(root[last] != 0);
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    assert(root[last] != 0);
    int root_cur = ++cnt;
    CreateSingleImp(1, n_, root_cur, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 150];        // 节点的左儿子编号
  int rs[N * 150];        // 节点的右儿子编号
  long long pro[N * 150]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);
        // printf("[%lld, %da], ", p.prime, p.num);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
      // printf("[%lld, %db]", vec.back().prime, vec.back().num);
    }
    // printf("\n");
  }

private:
  bool vis[M];        // i是否为质数
  long long prime[M]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

int main() {
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  // assert(m < 90);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        // assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    long long pri = fac_pri[i].back().prime;
    int id = disc.Id(pri);
    if (id == -1) {
      if (!last_id[pri]) {
        pers.CreateSingle(i, i - 1, i, pri);
      } else {
        // long long inv_p = Pow(pri, mod - 2ll);
        pers.CreateSingle(i, i - 1, last_id[pri], 1ll);
        pers.CreateSingle(i, i, i, pri);
      }
      last_id[pri] = i;
    } else {
      pers.Copy(i, i - 1);
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  return 0;
}


#include <bits/stdc++.h>

const int N = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = -INF;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[90]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    // assert(root[last] != 0);
    ++cnt;
    int root_cur = cnt;
    CreateSingleImp(1, n_, cnt, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 30];        // 节点的左儿子编号
  int rs[N * 30];        // 节点的右儿子编号
  long long pro[N * 30]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int> _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);
        // printf("[%lld, %da], ", p.prime, p.num);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
      // printf("[%lld, %db]", vec.back().prime, vec.back().num);
    }
    // printf("\n");
  }

private:
  bool vis[N];        // i是否为质数
  long long prime[N]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[N];

int main() {
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(1000, pri);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  assert(m < 90);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        // assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    long long pri = fac_pri[i].back().prime;
    int id = disc.Id(pri);
    if (id == -1) {
      if (!last_id[pri]) {
        pers.CreateSingle(i, i - 1, i, pri);
      } else {
        // long long inv_p = Pow(pri, mod - 2ll);
        pers.CreateSingle(i, i - 1, last_id[pri], 1ll);
        pers.CreateSingle(i, i, i, pri);
      }
      last_id[pri] = i;
    } else {
      pers.Copy(i, i - 1);
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  return 0;
}


#include <bits/stdc++.h>

const int N = 100010;
const int M = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int m;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    Build(1, n, root[0]);
  }

  // 第cur棵树等于第last棵树，即在cur位置没有更新
  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 第id个位置直接修改为x，得到编号为cur的新树
  void ChangeSingle(int cur, int id, long long x) {
    ChangeSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 第id个位置在原来数字的基础上乘以x，得到编号为cur的新树
  void IncreaseSingle(int cur, int id, long long x) {
    IncreaseSingleImp(1, n_, root[cur],  root[cur], id, x);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树，区间乘积初始化为1
  void Build(int l, int r, int& rt) {
    rt = ++cnt;
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点为rt_old的树的id位置改成x
  // 相当于在根节点为rt_old的旧树的基础上新添logn个节点，得到根为rt的新树
  void ChangeSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ChangeSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      ChangeSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // rt_old为根的树的id位置乘以x
  void IncreaseSingleImp(int l, int r, int& rt, int rt_old, int id, long long x) {
    rt = ++cnt;
    if (l == r) {
      pro[rt] = (pro[rt_old] * x) % mod;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      IncreaseSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      IncreaseSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    Up(rt);
  }

  // 询问根节点为rt的树在[L,R]区间内的乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  void Up(int rt) {
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 300];        // 节点的左儿子编号
  int rs[N * 300];        // 节点的右儿子编号
  long long pro[N * 300]; // 节点所表征区间的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Factorization {

public:
  Factorization() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        pri[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }
  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void Factorize(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && pri[i] <= sn; ++i) {
      if (n % pri[i] == 0) {
        PrimeFactor p(pri[i], 0);
        while (n % pri[i] == 0) {
          ++p.num;
          n /= pri[i];
        }
        vec.emplace_back(p);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
    }
  }

private:
  bool vis[M];        // i是否为质数
  long long pri[M];   // 质数集合，从小到大排列
  int cnt;            // 质数个数

}prime_fac; // class Factorization

class NumberPreprocess {

public:
  NumberPreprocess() {}

  void PreInverseElement(int n) {
    inv[1] = 1ll;
    for(int i = 2; i <= n; ++i) {
      inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    }
  }

  long long Inv(int i) {
    return inv[i];
  }

private:
  long long inv[M];

}np; // class NumberPreprocess

int n, q;
long long a[N];
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

int main() {

  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  prime_fac.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    prime_fac.Factorize(a[i], fac_pri[i]);
  }

  np.PreInverseElement(200000);
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    pers.Copy(i, i - 1);
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      long long tmp = 1ll;  // 记录pri的k次幂
      for (int k = 1; k <= num; ++k) {
        tmp *= pri;
        if (last_id[tmp]) {
          pers.IncreaseSingle(i, last_id[tmp], np.Inv(pri));
        }
        last_id[tmp] = i;
      }
    }
    pers.IncreaseSingle(i, i, a[i]);
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = pers.QueryProInterval(x, y);
    printf("%lld\n", ans);
    last = ans % n;
  }

  return 0;
}


#include <bits/stdc++.h>

const int N = 100010;
const int M = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = 0;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[90]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    assert(root[last] != 0);
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    assert(root[last] != 0);
    int root_cur = ++cnt;
    CreateSingleImp(1, n_, root_cur, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 150];        // 节点的左儿子编号
  int rs[N * 150];        // 节点的右儿子编号
  long long pro[N * 150]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int>& _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);
        // printf("[%lld, %da], ", p.prime, p.num);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
      // printf("[%lld, %db]", vec.back().prime, vec.back().num);
    }
    // printf("\n");
  }

private:
  bool vis[M];        // i是否为质数
  long long prime[M]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[M];

// #define Data
// #define Code

int main() {
// #ifdef Data
//   freopen("f.txt", "w", stdout);
//   printf("%d\n", 100000);
//   for (int i = 1; i <= 100000; ++i) {
//     printf("%d ", rand() % 200000);
//   }
//   printf("\n1\n");
//   int x = rand() % 100000;
//   int y = rand() % 100000;
//   if (x > y) {
//     std::swap(x, y);
//   }
//   printf("%d %d\n", x, y);
// #endif

// #ifdef Code
  // freopen("f.txt", "r", stdin);
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(448ll, pri); // 448 > sqrt(200000)
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  // assert(m < 90);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        // assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    if (!fac_pri[i].size()) {
      pers.Copy(i, i - 1);
    } else {
      long long pri = fac_pri[i].back().prime;
      int id = disc.Id(pri);
      if (id == -1) {
        if (!last_id[pri]) {
          pers.CreateSingle(i, i - 1, i, pri);
        } else {
          // long long inv_p = Pow(pri, mod - 2ll);
          pers.CreateSingle(i, i - 1, last_id[pri], 1ll);
          pers.CreateSingle(i, i, i, pri);
        }
        last_id[pri] = i;
      } else {
        pers.Copy(i, i - 1);
      }
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
// #endif
  return 0;
}


#include <bits/stdc++.h>

const int N = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = -INF;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[90]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  void Copy(int cur, int last) {
    root[cur] = root[last];
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    // printf("last: root[%d] = %d\n", last, root[last]);
    assert(root[last] != 0);
    ++cnt;
    int root_cur = cnt;
    CreateSingleImp(1, n_, cnt, root[last], id, x);
    root[cur] = root_cur;
    // printf("cur: root[%d] = %d\n", cur, root[cur]);
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 20];        // 节点的左儿子编号
  int rs[N * 20];        // 节点的右儿子编号
  long long pro[N * 20]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int> _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
    }
  }

private:
  bool vis[N];        // i是否为质数
  long long prime[N]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[N];

int main() {
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(1000, pri);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  assert(m < 90);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    long long pri = fac_pri[i].back().prime;
    int id = disc.Id(pri);
    if (id == -1) {
      if (!last_id[pri]) {
        pers.CreateSingle(i, i - 1, i, pri);
      } else {
        long long inv_p = Pow(pri, mod - 2);
        pers.CreateSingle(i, i - 1, last_id[pri], inv_p);
        pers.CreateSingle(i, i, i, pri);
      }
      last_id[pri] = i;
    } else {
      pers.Copy(i, i - 1);
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  return 0;
}


#include <bits/stdc++.h>

const int N = 200010;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int ReadInt() {
  int x = 0, f = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
  while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
  return x * f;
}

class SegmentTree {

public:
  SegmentTree() {}

  // 初始化数组长度n
  void Init(int n) {
    n_ = n;
  }

  // 对数组v[1,n]建树
  void Build(int l, int r, int rt, int v[]) {
    if (l == r) {
      mx_[rt] = v[l];
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 修改编号为id的数字为x
  void ChangeSingle(int l, int r, int rt, int id, int x) {
    // 遍历终点：更新标记和维护值
    if (l == r) {
      mx_[rt] = x;   // 维护值更新
      return;
    }
    int m = (l + r) >> 1;
    if (id <= m) {
      ChangeSingle(l, m, rt << 1, id, x);
    } else {
      ChangeSingle(m + 1, r, rt << 1 | 1, id, x);
    }
    Up(rt);
  }

  // 求区间[L,R]内的最大值
  int MaxInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return mx_[rt];
    }
    int m = (l + r) >> 1;
    int ans = -INF;
    if (L <= m) {
      ans = std::max(ans, MaxInterval(l, m, rt << 1, L, R));
    }
    if (R > m) {
      ans = std::max(ans, MaxInterval(m + 1, r, rt << 1 | 1, L, R));
    }
    return ans;
  }

private:
  void Up(int rt) {
    // 1. 维护值上传
    mx_[rt] = std::max(mx_[rt << 1], mx_[rt << 1 | 1]);
  }

  int n_;
  int mx_[N<<2|1];        // 区间最大值
}seg[100]; // class SegmentTree

class PersistentSegmentTree {

public:
  PersistentSegmentTree() {
    cnt = 0;
    memset(root, 0, sizeof(root));
  }

  void Init(int n) {
    n_ = n;
    root[0] = ++cnt;
    Build(1, n, root[0]);
  }

  // 把第编号为last的旧树的第id个位置修改为x，得到编号为cur的新树
  // cur可以等于last，弃用之前的root[last]，使用新的root[cur]
  void CreateSingle(int cur, int last, int id, long long x) {
    assert(root[cur] == 0);
    assert(root[last] != 0);
    ++cnt;
    int root_cur = cnt;
    CreateSingleImp(1, n_, cnt, root[last], id, x);
    root[cur] = root_cur;
  }

  // 询问第R棵树的[L,R]区间的乘积
  long long QueryProInterval(int L, int R) {
    return ProInterval(1, n_, root[R], L, R);
  }

private:

  // 构建第一棵空树
  void Build(int l, int r, int rt) {
    pro[rt] = 1ll;
    if (l == r) {
      return;
    }
    ls[rt] = ++cnt;
    rs[rt] = ++cnt;
    int m = (l + r) >> 1;
    Build(l, m, ls[rt]);
    Build(m + 1, r, rs[rt]);
  }

  // 将根节点未rt_old的树的id位置改成x，得到根为rt的新树
  void CreateSingleImp(int l, int r, int rt, int rt_old, int id, long long x) {
    if (l == r) {
      pro[rt] = x;
      return;
    }
    int m = (l + r) >> 1;
    ls[rt] = ls[rt_old];
    rs[rt] = rs[rt_old];
    if (id <= m) {
      ls[rt] = ++cnt;
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      rs[rt] = ++cnt;
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为rt的树的区间乘积
  long long ProInterval(int l, int r, int rt, int L, int R) {
    if (L <= l && r <= R) {
      return pro[rt];
    }
    int m = (l + r) >> 1;
    long long ans = 1ll;
    if (L <= m) {
      ans = (ans * ProInterval(l, m, ls[rt], L, R)) % mod;
    }
    if (R > m) {
      ans = (ans * ProInterval(m + 1, r, rs[rt], L, R)) % mod;
    }
    return ans;
  }

  int n_;
  int cnt;                // 树中的节点个数
  int ls[N * 100];        // 节点的左儿子编号
  int rs[N * 100];        // 节点的右儿子编号
  long long pro[N * 100]; // 节点的乘积
  int root[N]; // 第i棵树的根节点编号
}pers; // class PersistentSegmentTree

class Discretization {

public:
  Discretization() {
    vec_.clear();
  }

  void Init() {
    vec_.clear();
  }

  // 添加一个元素
  void Add(int x) {
    vec_.push_back(x);
  }

  // 排序后离散化
  void Build() {
    std::sort(vec_.begin(), vec_.end());
    vec_.erase(std::unique(vec_.begin(), vec_.end()), vec_.end());
  }

  // 查询离散化后的编号
  int Id(int x) {
    auto y = std::lower_bound(vec_.begin(), vec_.end(), x);
    if (y == vec_.end() || *y != x) {
      return -1;
    } else {
      return y - vec_.begin() + 1;
    }
  }

  // 输出离散化后第id(1<=id<=Size())个元素的值
  int Val(int id) {
    return vec_[id - 1];
  }

  int Size() {
    return vec_.size();
  }

private:
  std::vector<int> vec_;
}disc;

typedef std::pair<long long, int> PrimeFactor;
#define prime first
#define num second

class Number {

public:
  Number() {
    memset(vis, false, sizeof(vis));
    cnt = 0;
  }

  // 预处理[1,n]中的质数，时间复杂度O(nlogn)
  void PrePrime(long long n, std::vector<int> _prime) {
    _prime.clear();
    for (long long i = 2ll; i <= n; ++i) {
      if (!vis[i]) {
        prime[cnt++] = i;
        _prime.push_back(i);
        for (long long j = i + i; j <= n; j += i) {
          vis[j] = true;
        }
      }
    }

  }

  // 对n进行质因子分解，时间复杂度O(sqrt n)
  void FactorPrime(long long n, std::vector<PrimeFactor>& vec) {
    long long sn = sqrt(n);
    vec.clear();
    for (int i = 0; i < cnt && prime[i] <= sn; ++i) {
      if (n % prime[i] == 0) {
        PrimeFactor p(prime[i], 0);
        disc.Add(prime[i]);
        while (n % prime[i] == 0) {
          ++p.num;
          n /= prime[i];
        }
        vec.emplace_back(p);

        if (n == 1ll) {
          break;
        }
      }
    }

    if (n != 1) {
      vec.emplace_back(PrimeFactor(n, 1));
    }
  }

private:
  bool vis[N];        // i是否为质数
  long long prime[N]; // 质数
  int cnt;            // 质数个数

}number; // class Number

long long Pow(long long a, long long b) {
  long long ans = 1ll;
  for (long long tmp = a; b;) {
    if (b & 1) {
      ans = (ans * tmp) % mod;
    }
    tmp = (tmp * tmp) % mod;
    b >>= 1ll;
  }
  return ans;
}

int n, q;
long long a[N];
int b[N];
int m;
std::vector<PrimeFactor> fac_pri[N]; // 第i个数的质因子分解结果
std::vector<int> pri; // 小于1000的质因子集合
int last_id[N];

int main() {
  scanf("%d", &n);

  // 预处理不大于根号a_i的素因子
  disc.Init();
  number.PrePrime(1000, pri);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    number.FactorPrime(a[i], fac_pri[i]);
    b[i] = 0;
  }
  disc.Build();
  m = disc.Size();
  assert(m < 100);
  for (int i = 1; i <= m; ++i) {
    seg[i].Init(n);
    seg[i].Build(1, n, 1, b);
  }
  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < fac_pri[i].size(); ++j) {
      long long pri = fac_pri[i][j].prime;
      int num = fac_pri[i][j].num;
      int id = disc.Id(pri);
      // printf("%d: %lld->%d, %d\n", i, pri, id, num);
      if (id != -1) {
        assert(id >= 1 && id <= m);
        seg[id].ChangeSingle(1, n, 1, i, num);
      }
    }
  }

  // 预处理大于根号a_i的素因子
  pers.Init(n);
  memset(last_id, 0, sizeof(last_id));
  for (int i = 1; i <= n; ++i) {
    long long pri = fac_pri[i].back().prime;
    int id = disc.Id(pri);
    if (id == -1) {
      if (!last_id[pri]) {
        pers.CreateSingle(i, i - 1, i, pri);
      } else {
        long long inv_p = Pow(pri, mod - 2);
        pers.CreateSingle(i, i - 1, last_id[pri], inv_p);
        pers.CreateSingle(i, i, i, pri);
      }
      last_id[pri] = i;
    }
  }

  scanf("%d", &q);
  int last = 0;
  for (int i = 1; i <= q; ++i) {
    int x = ReadInt();
    int y = ReadInt();
    x = (last + x) % n + 1;
    y = (last + y) % n + 1;
    if (x > y) {
      std::swap(x, y);
    }
    long long ans = 1ll;
    // 不大于根号a_i的素因子幂次的LCM
    for (int j = 1; j <= m; ++j) {
      int num = seg[j].MaxInterval(1, n, 1, x, y);
      ans = (ans * Pow(disc.Val(j), num)) % mod;
    }
    // printf("[%d, %d]: %lld\n", x, y, ans);

    // 大于根号a_i的素因子的LCM
    ans = (ans * pers.QueryProInterval(x, y)) % mod;
    printf("%lld\n", ans);
    last = ans % n;
  }
  return 0;
}