#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 * 400];        // 节点的左儿子编号
  int rs[N * 400];        // 节点的右儿子编号
  long long pro[N * 400]; // 节点所表征区间的乘积
  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) {
    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 * 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);
        // 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 = 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;
}

// 维护n_个向量，维度下标范围是[1,num_]
class SegmentTree2 {

public:
  SegmentTree2() {}

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

  // 使用n_个m_维向量v[1,2,...,n_]建树，其中v[i] = (v[i][1],...,v[i][num_])
  void Build(int l, int r, int rt, int v[N][90]) {
    if (l == r) {
      for (int i = 1; i <= num_; ++i) {
        mx_[rt][i] = v[l][i];
      }
      return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1, v);
    Build(m + 1, r, rt << 1 | 1, v);
    Up(rt);
  }

  // 向量v[id]的第num维改为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);
  }

  // 求v[L,R]的R-L+1个向量中每一维的最大值
  // ans: 最大值，需要在外面初始化
  void MaxInterval(int l, int r, int rt, int L, int R, int* ans) {
    if (L <= l && r <= R) {
      for (int i = 1; i <= num_; ++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 <= num_; ++i) {
      mx_[rt][i] = std::max(mx_[rt << 1][i], mx_[rt << 1 | 1][i]);
    }
  }

  int n_;               // 数组长度
  int num_;             // 区间最大值个数
  int mx_[N<<2|1][90];  // 区间最大值
}seg; // class SegmentTree2

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) {
    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) {
    // int root_cur = ++cnt;
    CreateSingleImp(1, n_, root[cur], 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:

  // 构建第一棵空树，区间乘积初始化为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 CreateSingleImp(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) {
      CreateSingleImp(l, m, ls[rt], ls[rt_old], id, x);
    } else {
      CreateSingleImp(m + 1, r, rs[rt], rs[rt_old], id, x);
    }
    pro[rt] = (pro[ls[rt]] * pro[rs[rt]]) % mod;
  }

  // 询问根节点为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;
  }

  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[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][90];
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]);
  }
  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);
      if (id != -1) {
        b[i][id] = num;
      }
    }
  }
  seg.Init(n, m);
  seg.Build(1, n, 1, b);

  // 预处理大于根号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 {
          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
    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;
    }

    // 大于根号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 * 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);
        // 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 * 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);
        // 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 = 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 * 200];        // 节点的左儿子编号
  int rs[N * 200];        // 节点的右儿子编号
  long long pro[N * 200]; // 节点所表征区间的乘积
  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]) {
        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 Factorize(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);
        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[M];        // i是否为质数
  long long prime[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 = 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]);
  }

  // 把第编号为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 * 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;
    }
  }

  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;

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;
}

class GcdInterval {

public:
  GcdInterval() {}

  long long Gcd(long long a, long long b) {
    return !b ? a : Gcd(b, a % b);
  }

  // 使用a[1,n]初始化vec[]数组
  void Init(int n, long long a[]) {
    for (int i = 1; i <= n; ++i) {
      vec[i].clear();
    }
    vec[1].push_back(std::pair<int, long long>(1, a[1]));
    for (int i = 2; i <= n; ++i) {
      long long gcd_tmp = a[i];
      int l_tmp = i;
      for (size_t j = 0; j < vec[i - 1].size(); ++j) {
        // 计算到第j段左端点位置的gcd
        long long gcd_nxt = Gcd(vec[i - 1][j].second, gcd_tmp);
        // 如果gcd发生变化，则添加上一段的左端点和gcd
        if (gcd_nxt != gcd_tmp) {
          vec[i].push_back(std::pair<int, long long>(l_tmp, gcd_tmp));
          gcd_tmp = gcd_nxt;
        }
        l_tmp = vec[i - 1][j].first;
      }
      // 加入最长一段的左端点和gcd
      vec[i].push_back(std::pair<int, long long>(l_tmp, gcd_tmp));
    }

    // Debug
    // for (int i = 1; i <= n; ++i) {
    //   for (int j = 0; j < vec[i].size(); ++j) {
    //     printf("gcd[%d, %d] = %lld\n", vec[i][j].first, i, vec[i][j].second);
    //   }
    // }
  }

  // 计算区间a[l,r]的gcd
  long long Cal(int l, int r) {
    for (size_t i = 0; i < vec[r].size(); ++i) {
      if (l >= vec[r][i].first) {
        return vec[r][i].second;
      }
    }
    return -1ll;
  }

  std::vector< std::pair<int, long long> > vec[N]; // vec[i]: 以i结尾的连续gcd区间左端点和gcd值，按照左端点从大到小排列

private:

}; // class GcdInterval

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;
}

GcdInterval gcd_int;

int n, q;
long long a[N];
long long pro[N];
long long pro_inv[N];

int main() {
  scanf("%d", &n);
  pro[0] = 1ll;
  pro_inv[0] = Pow(pro[0], mod - 2ll);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    pro[i] = (i == 1 ? a[i] : (pro[i - 1] * a[i]) % mod);
    pro_inv[i] = Pow(pro[i], mod - 2ll);
  }
  gcd_int.Init(n, a);

  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;
    if (x == y) {
      ans = a[x] % mod;
    } else {
      ans = pro[y] * pro_inv[x - 1];
      long long tmp = gcd_int.Cal(x, y);
      assert(tmp != -1ll);
      ans = (ans * Pow(tmp, mod - 2)) % 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 * 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);
        // 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 = 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 * 400];        // 节点的左儿子编号
  int rs[N * 400];        // 节点的右儿子编号
  long long pro[N * 400]; // 节点所表征区间的乘积
  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 = 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] = (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[K];        // 节点的左儿子编号
  int rs[K];        // 节点的右儿子编号
  long long 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;
}


//知识点：线段树，主席树
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define LL long long
const int kN = 1e5 + 10;
const int kMax = 2e5;
const int mod = 1e9 + 7;
//=============================================================
int p_num, p[kN];
bool vis[kN];
int n, m, ans, a[kN], last[kN], lastv[kN];
int root[kN];
//=============================================================
inline int read() {
  int f = 1, w = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) {
    w = (w << 3) + (w << 1) + (ch ^ '0');
  }
  return f * w;
}
void Chkmax(int &fir_, int sec_) {
  if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
  if (sec_ < fir_) fir_ = sec_;
}
void Euler() {
  for (int i = 2; i <= kMax; ++ i) {
    if (! vis[i]) p[++ p_num] = i;
    for (int j = 1; j <= p_num && i * p[j] <= kMax; ++ j) {
      vis[i * p[j]] = true;
      if (i % p[j] == 0) break;
    }
  }
}
int QPow(int x_, int y_) {
  x_ %= mod;
  int ret = 1;
  for (; y_; y_ >>= 1) {
    if (y_ & 1) ret = 1ll * ret * x_ % mod;
    x_ = 1ll * x_ * x_ % mod;
  }
  return ret;
}
int Inv(int x_) {
  return QPow(x_, mod - 2);
}
namespace Hjt {
  #define ls (lson[now_])
  #define rs (rson[now_])
  #define mid ((L_+R_)>>1)
  int node_num, lson[kN << 6], rson[kN << 6], t[kN << 6];
  void Init() {
    t[0] = 1;
  }
  void Insert(int &now_, int pre_, int L_, int R_, int pos_, int val_) {
    now_ = ++ node_num;
    t[now_] = 1ll * t[pre_] * val_ % mod;
    if (L_ == R_) return ;
    ls = lson[pre_], rs = rson[pre_];
    if (pos_ <= mid) Insert(ls, lson[pre_], L_, mid, pos_, val_);
    else Insert(rs, rson[pre_], mid + 1, R_, pos_, val_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
  #undef ls
  #undef rs
  #undef mid
}
#define ls (now_<<1)
#define rs (now_<<1|1)
#define mid ((L_+R_)>>1)
struct Seg {
  int t[kN << 2];
  void Build(int now_, int L_, int R_) {
    t[now_] = 1;
    if (L_ == R_) return ;
    Build(ls, L_, mid);
    Build(rs, mid +1, R_);
  }
  void Pushup(int now_) {
    t[now_] = std::max(t[ls], t[rs]);
  }
  void Insert(int now_, int L_, int R_, int pos_, int val_) {
    if (L_ == R_) {
      t[now_] = 1ll * t[now_] * val_ % mod;
      return ;
    }
    if (pos_ <= mid) Insert(ls, L_, mid, pos_, val_);
    else Insert(rs, mid + 1, R_, pos_, val_);
    Pushup(now_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
} t[93];
#undef ls
#undef rs
#undef mid
void Insert(int pos_) {
  int val = a[pos_] = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    int d = p[i], delta = 1;
    if (val == 1) break;
    if (val % d) continue ;
    while (val % d == 0) {
      val /= d;
      delta *= d;
    }
    t[i].Insert(1, 1, n, pos_, delta);
  }
  // root[pos_] = root[pos_ - 1];
  // if (lastv[val]) {
  //   Hjt::Insert(root[pos_], root[pos_], 1, n, lastv[val], Inv(val));
  // }
  // Hjt::Insert(root[pos_], root[pos_], 1, n, pos_, val);
  // lastv[val] = pos_;
}
int Query(int l_, int r_) {
  int ret = 1;
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    ret = 1ll * ret * t[i].Query(1, 1, n, l_, r_) % mod;
  }
  ret = 1ll * ret * Hjt::Query(root[r_], 1, n, l_, r_);
  return ret;
}
void Prepare() {
  Euler();
  Hjt::Init();
  n = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) t[i].Build(1, 1, n);
  for (int i = 1; i <= n; ++ i) Insert(i);
}
//=============================================================
int main() {
  Prepare();
  m = read();
  while (m --) {
    int l = (read() + ans) % n + 1, r = (read() + ans) % n + 1;
    if (l > r) std::swap(l, r);
    // printf("%d\n", ans = Query(l, r));
  }
  return 0;
}


//知识点：线段树，主席树
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define LL long long
const int kN = 1e5 + 10;
const int kMax = 2e5;
const int mod = 1e9 + 7;
//=============================================================
int p_num, p[kMax + 10];
bool vis[kMax + 10];
int n, m, ans, a[kN], last[kN], lastv[kN];
int root[kN];
//=============================================================
inline int read() {
  int f = 1, w = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) {
    w = (w << 3) + (w << 1) + (ch ^ '0');
  }
  return f * w;
}
void Chkmax(int &fir_, int sec_) {
  if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
  if (sec_ < fir_) fir_ = sec_;
}
void Euler() {
  for (int i = 2; i <= kMax; ++ i) {
    if (! vis[i]) p[++ p_num] = i;
    for (int j = 1; j <= p_num && i * p[j] <= kMax; ++ j) {
      vis[i * p[j]] = true;
      if (i % p[j] == 0) break;
    }
  }
}
int QPow(int x_, int y_) {
  x_ %= mod;
  int ret = 1;
  for (; y_; y_ >>= 1) {
    if (y_ & 1) ret = 1ll * ret * x_ % mod;
    x_ = 1ll * x_ * x_ % mod;
  }
  return ret;
}
int Inv(int x_) {
  return QPow(x_, mod - 2);
}
namespace Hjt {
  #define ls (lson[now_])
  #define rs (rson[now_])
  #define mid ((L_+R_)>>1)
  int node_num, lson[kN << 6], rson[kN << 6], t[kN << 6];
  void Init() {
    t[0] = 1;
  }
  void Insert(int &now_, int pre_, int L_, int R_, int pos_, int val_) {
    now_ = ++ node_num;
    t[now_] = 1ll * t[pre_] * val_ % mod;
    if (L_ == R_) return ;
    ls = lson[pre_], rs = rson[pre_];
    if (pos_ <= mid) Insert(ls, lson[pre_], L_, mid, pos_, val_);
    else Insert(rs, rson[pre_], mid + 1, R_, pos_, val_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
  #undef ls
  #undef rs
  #undef mid
}
#define ls (now_<<1)
#define rs (now_<<1|1)
#define mid ((L_+R_)>>1)
struct Seg {
  int t[kN << 2];
  void Build(int now_, int L_, int R_) {
    t[now_] = 1;
    if (L_ == R_) return ;
    Build(ls, L_, mid);
    Build(rs, mid +1, R_);
  }
  void Pushup(int now_) {
    t[now_] = std::max(t[ls], t[rs]);
  }
  void Insert(int now_, int L_, int R_, int pos_, int val_) {
    if (L_ == R_) {
      t[now_] = 1ll * t[now_] * val_ % mod;
      return ;
    }
    if (pos_ <= mid) Insert(ls, L_, mid, pos_, val_);
    else Insert(rs, mid + 1, R_, pos_, val_);
    Pushup(now_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
} t[93];
#undef ls
#undef rs
#undef mid
void Insert(int pos_) {
  int val = a[pos_] = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    int d = p[i], delta = 1;
    if (val == 1) break;
    if (val % d) continue ;
    while (val % d == 0) {
      val /= d;
      delta *= d;
    }
    t[i].Insert(1, 1, n, pos_, delta);
  }
  root[pos_] = root[pos_ - 1];
  if (lastv[val]) {
    Hjt::Insert(root[pos_], root[pos_], 1, n, lastv[val], Inv(val));
  }
  Hjt::Insert(root[pos_], root[pos_], 1, n, pos_, val);
  lastv[val] = pos_;
}
int Query(int l_, int r_) {
  int ret = 1;
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    ret = 1ll * ret * t[i].Query(1, 1, n, l_, r_) % mod;
  }
  ret = 1ll * ret * Hjt::Query(root[r_], 1, n, l_, r_);
  return ret;
}
void Prepare() {
  Euler();
  Hjt::Init();
  n = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) t[i].Build(1, 1, n);
  for (int i = 1; i <= n; ++ i) Insert(i);
}
//=============================================================
int main() {
  Prepare();
  m = read();
  while (m --) {
    int l = (read() + ans) % n + 1, r = (read() + ans) % n + 1;
    if (l > r) std::swap(l, r);
    printf("%d\n", ans = Query(l, r));
  }
  return 0;
}


//知识点：线段树，主席树
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define LL long long
const int kN = 1e5 + 10;
const int kMax = 2e5;
const int mod = 1e9 + 7;
//=============================================================
int p_num, p[kN];
bool vis[kN];
int n, m, ans, a[kN], last[kN], lastv[kN];
int root[kN];
//=============================================================
inline int read() {
  int f = 1, w = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) {
    w = (w << 3) + (w << 1) + (ch ^ '0');
  }
  return f * w;
}
void Chkmax(int &fir_, int sec_) {
  if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
  if (sec_ < fir_) fir_ = sec_;
}
void Euler() {
  for (int i = 2; i <= kMax; ++ i) {
    if (! vis[i]) p[++ p_num] = i;
    for (int j = 1; j <= p_num && i * p[j] <= kMax; ++ j) {
      vis[i * p[j]] = true;
      if (i % p[j] == 0) break;
    }
  }
}
int QPow(int x_, int y_) {
  x_ %= mod;
  int ret = 1;
  for (; y_; y_ >>= 1) {
    if (y_ & 1) ret = 1ll * ret * x_ % mod;
    x_ = 1ll * x_ * x_ % mod;
  }
  return ret;
}
int Inv(int x_) {
  return QPow(x_, mod - 2);
}
namespace Hjt {
  #define ls (lson[now_])
  #define rs (rson[now_])
  #define mid ((L_+R_)>>1)
  int node_num, lson[kN << 6], rson[kN << 6], t[kN << 6];
  void Init() {
    t[0] = 1;
  }
  void Insert(int &now_, int pre_, int L_, int R_, int pos_, int val_) {
    now_ = ++ node_num;
    t[now_] = 1ll * t[pre_] * val_ % mod;
    if (L_ == R_) return ;
    ls = lson[pre_], rs = rson[pre_];
    if (pos_ <= mid) Insert(ls, lson[pre_], L_, mid, pos_, val_);
    else Insert(rs, rson[pre_], mid + 1, R_, pos_, val_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
  #undef ls
  #undef rs
  #undef mid
}
#define ls (now_<<1)
#define rs (now_<<1|1)
#define mid ((L_+R_)>>1)
struct Seg {
  int t[kN << 2];
  void Pushup(int now_) {
    if (! t[ls]) t[ls] = 1;
    if (! t[rs]) t[rs] = 1;
    t[now_] = 1ll * t[ls] * t[rs] % mod;
  }
  void Insert(int now_, int L_, int R_, int pos_, int val_) {
    if (L_ == R_) {
      if (! t[now_]) t[now_] = 1;
      t[now_] = 1ll * t[now_] * val_ % mod;
      return ;
    }
    if (pos_ <= mid) Insert(ls, L_, mid, pos_, val_);
    else Insert(rs, mid + 1, R_, pos_, val_);
    Pushup(now_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) {

      if (! t[now_]) t[now_] = 1;
      return t[now_];
    }
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
} t[100];
#undef ls
#undef rs
#undef mid
void Insert(int pos_) {
  int val = a[pos_] = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    int d = p[i], delta = 1;
    if (val == 1) break;
    if (val % d) continue ;
    while (val % d == 0) {
      val /= d;
      delta *= d;
    }
    t[i].Insert(1, 1, n, pos_, delta);
  }
  root[pos_] = root[pos_ - 1];
  if (lastv[val]) {
    Hjt::Insert(root[pos_], root[pos_], 1, n, lastv[val], Inv(val));
  }
  Hjt::Insert(root[pos_], root[pos_], 1, n, pos_, val);
  lastv[val] = pos_;
}
int Query(int l_, int r_) {
  int ret = 1;
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    ret = 1ll * ret * t[i].Query(1, 1, n, l_, r_) % mod;
  }
  ret = 1ll * ret * Hjt::Query(root[r_], 1, n, l_, r_);
  return ret;
}
void Prepare() {
  Euler();
  Hjt::Init();
  n = read();
  for (int i = 1; i <= n; ++ i) Insert(i);
}
//=============================================================
int main() {
  Prepare();
  m = read();
  while (m --) {
    int l = (read() + ans) % n + 1, r = (read() + ans) % n + 1;
    if (l > r) std::swap(l, r);
    printf("%d\n", ans = Query(l, r));
  }
  return 0;
}


//知识点：线段树，主席树
/*
By:Luckyblock
Why give me a Re!
Tell me reason!
*/
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define LL long long
const int kN = 1e5 + 10;
const int kMax = 2e5;
const int mod = 1e9 + 7;
//=============================================================
int p_num, p[kN];
bool vis[kN];
int n, m, ans, a[kN], last[kN], lastv[kN];
int root[kN];
//=============================================================
inline int read() {
  int f = 1, w = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) {
    w = (w << 3) + (w << 1) + (ch ^ '0');
  }
  return f * w;
}
void Chkmax(int &fir_, int sec_) {
  if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
  if (sec_ < fir_) fir_ = sec_;
}
void Euler() {
  for (int i = 2; i <= kMax; ++ i) {
    if (! vis[i]) p[++ p_num] = i;
    for (int j = 1; j <= p_num && i * p[j] <= kMax; ++ j) {
      vis[i * p[j]] = true;
      if (i % p[j] == 0) break;
    }
  }
}
int QPow(int x_, int y_) {
  x_ %= mod;
  int ret = 1;
  for (; y_; y_ >>= 1) {
    if (y_ & 1) ret = 1ll * ret * x_ % mod;
    x_ = 1ll * x_ * x_ % mod;
  }
  return ret;
}
int Inv(int x_) {
  return QPow(x_, mod - 2);
}
namespace Hjt {
  #define ls (lson[now_])
  #define rs (rson[now_])
  #define mid ((L_+R_)>>1)
  int node_num, lson[kN << 6], rson[kN << 6], t[kN << 6];
  void Init() {
    t[0] = 1;
  }
  void Insert(int &now_, int pre_, int L_, int R_, int pos_, int val_) {
    now_ = ++ node_num;
    t[now_] = 1ll * t[pre_] * val_ % mod;
    if (L_ == R_) return ;
    ls = lson[pre_], rs = rson[pre_];
    if (pos_ <= mid) Insert(ls, lson[pre_], L_, mid, pos_, val_);
    else Insert(rs, rson[pre_], mid + 1, R_, pos_, val_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) return t[now_];
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
  #undef ls
  #undef rs
  #undef mid
}
#define ls (now_<<1)
#define rs (now_<<1|1)
#define mid ((L_+R_)>>1)
struct Seg {
  int t[kN << 2];
  void Pushup(int now_) {
    if (! t[ls]) t[ls] = 1;
    if (! t[rs]) t[rs] = 1;
    t[now_] = 1ll * t[ls] * t[rs] % mod;
  }
  void Insert(int now_, int L_, int R_, int pos_, int val_) {
    if (L_ == R_) {
      if (! t[now_]) t[now_] = 1;
      t[now_] = 1ll * t[now_] * val_ % mod;
      return ;
    }
    if (pos_ <= mid) Insert(ls, L_, mid, pos_, val_);
    else Insert(rs, mid + 1, R_, pos_, val_);
    Pushup(now_);
  }
  int Query(int now_, int L_, int R_, int l_, int r_) {
    if (l_ <= L_ && R_ <= r_) {

      if (! t[now_]) t[now_] = 1;
      return t[now_];
    }
    int ret = 1;
    if (l_ <= mid) ret = 1ll * ret * Query(ls, L_, mid, l_, r_) % mod;
    if (r_ > mid) ret = 1ll * ret * Query(rs, mid + 1, R_, l_, r_) % mod;
    return ret;
  }
} t[100];
#undef ls
#undef rs
#undef mid
void Insert(int pos_) {
  int val = a[pos_] = read();
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    int d = p[i], delta = 1;
    if (val == 1) break;
    if (val % d) continue ;
    while (val % d == 0) {
      val /= d;
      delta *= d;
    }
    t[i].Insert(1, 1, n, pos_, delta);
  }
  root[pos_] = root[pos_ - 1];
  if (lastv[val]) {
    Hjt::Insert(root[pos_], root[pos_], 1, n, lastv[val], Inv(val));
  }
  Hjt::Insert(root[pos_], root[pos_], 1, n, pos_, val);
  lastv[val] = pos_;
}
int Query(int l_, int r_) {
  int ret = 1;
  for (int i = 1; p[i] * p[i] <= kMax; ++ i) {
    ret = 1ll * ret * t[i].Query(1, 1, n, l_, r_) % mod;
  }
  ret = 1ll * ret * Hjt::Query(root[r_], 1, n, l_, r_);
  return ret;
}
void Prepare() {
  Euler();
  Hjt::Init();
  n = read();
  for (int i = 1; i <= n; ++ i) Insert(i);
}
//=============================================================
int main() {
  Prepare();
  m = read();
  while (m --) {
    int l = (read() + ans) % n + 1, r = (read() + ans) % n + 1;
    if (l > r) std::swap(l, r);
    printf("%d\n", ans = Query(l, r));
  }
  return 0;
}