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

template <int mod = (int)(1e9 + 7)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const
      noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const
      noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const
      noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const
      noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const
      noexcept {
    return x == p.x;
  }
  constexpr bool operator!=(const ModInt &p) const
      noexcept {
    return x != p.x;
  }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while(n) {
      if(n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(
      ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is,
                                       ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

// 0-indexed
template <class T>
struct SegmentTree {
  // a,b,c: T, e:T(unit)
  // abc = (ab)c = a(bc)
  // ae = ea = a
  typedef function<T(T &, T &)> F;
  int n;
  F f;
  T unit;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int newn, F f, T t) : f(f), unit(t) {
    init(newn);
  }
  SegmentTree(const vector<T> &v, F f, T t)
      : f(f), unit(t) {
    int _n = v.size();
    init(v.size());
    for(int i = 0; i < _n; ++i) dat[n + i] = v[i];
    for(int i = n - 1; i; --i)
      dat[i] = f(dat[i << 1], dat[(i << 1) | 1]);
  }
  void init(int newn) {
    n = 1;
    while(n < newn) n <<= 1;
    dat.assign(n << 1, unit);
  }

  // "go up" process
  void update(int k, T newdata) {
    dat[k += n] = newdata;
    while(k >>= 1) {
      dat[k] = f(dat[(k << 1) | 0], dat[(k << 1) | 1]);
    }
  }
  // [a,b)
  T query(int a, int b) {
    T vl = unit, vr = unit;
    for(int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if(l & 1) vl = f(vl, dat[l++]);
      if(r & 1) vr = f(dat[--r], vr);
    }
    return f(vl, vr);
  }
};

long long n, q;
vector<long long> p,
    prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37},
    cnt;
vector<ModInt<>> sum;
SegmentTree<map<int, int>> seg;

void prepair();

int main() {
  cin >> n >> q;
  p.resize(n);
  for(int i = 0; i < n; ++i) cin >> p[i];
  prepair();
  for(int i = 0; i < q; ++i) {
    int l, r;
    cin >> l >> r;
    ModInt<> res = sum[r] - sum[l - 1];
    map<int, int> mp = seg.query(l - 1, r);
    for(auto p : mp)
      for(int j = 0; j < p.second; ++j) res *= p.first;
    cout << res << endl;
  }
  return 0;
}

void prepair() {
  cnt.assign(n, 0);
  sum.resize(n + 1, 0);
  for(int i = 0; i < n; ++i) {
    int now = i + 1;
    do {
      ++cnt[i];
      now = p[now - 1];
      sum[i + 1] += now;
    } while(now != i + 1);
  }
  for(int i = 0; i < n; ++i) {
    sum[i + 1] /= cnt[i];
    sum[i + 1] += sum[i];
  }
  auto f = [](map<int, int> &l, map<int, int> &r) {
    map<int, int> res = l;
    for(auto p : r)
      res[p.first] = max(res[p.first], p.second);
    return res;
  };
  seg = SegmentTree<map<int, int>>(n, f, map<int, int>());
  for(int i = 0; i < n; ++i) {
    map<int, int> mp;
    int x = cnt[i];
    for(int j = 2; j * j <= x; ++j)
      while(x % j == 0) {
        ++mp[j];
        x /= j;
      }
    if(x > 1) ++mp[x];
    seg.update(i, mp);
  }
}


Measured memory_bytes: 46096