#include <iostream>
#include <vector>
#include <cassert>

using namespace std;
using ll = long long;
constexpr ll INF = 1 << 28;

template <typename Base>
class SegmentTree
{
public:
    using BaseAlgebra = Base;
    using AccMonoid = typename BaseAlgebra::AccMonoid;
    using OpMonoid = typename BaseAlgebra::OpMonoid;
    using T = typename BaseAlgebra::T;
    using F = typename BaseAlgebra::OpMonoid::T;

    SegmentTree(const int n) : data_num(n), height(__lg(2 * data_num - 1)), size(1 << (1 + height)), half(size >> 1), value(size, AccMonoid::identity()), action(size, OpMonoid::identity()) { assert(n > 0); }
    SegmentTree(const std::vector<T>& val) : data_num(val.size()), height(__lg(2 * data_num - 1)), size(1 << (1 + height)), half(size >> 1), value(size), action(size, OpMonoid::identity())
    {
        for (int data = 0; data < half; data++) {
            if (data < data_num) {
                value[data + half] = val[data];
            } else {
                value[data + half] = AccMonoid::identity();
            }
        }
        for (int node = half - 1; node >= 1; node--) {
            value[node] = acc(value[2 * node], value[2 * node + 1]);
        }
    }

    T get(const int a) const
    {
        assert(0 <= a and a < data_num);
        return accumulate(a, a + 1);
    }

    void set(const int a, const T& val)
    {
        assert(0 <= a and a < data_num);
        const int node = a + half;
        value[node] = val;
        for (int i = node / 2; i > 0; i /= 2) {
            value[i] = acc(value[2 * i], value[2 * i + 1]);
        }
    }

    T accumulate(const int a, const int b) const  // Accumulate (a,b]
    {
        assert(0 <= a and a < b and b <= data_num);
        return accumulateRec(1, 0, half, a, b);
    }

    void modify(const int a, const int b, const F& f)  // Apply f on (a,b]
    {
        assert(0 <= a and a < b and b <= data_num);
        if (f == OpMonoid::identity()) {
            return;
        }
        modifyRec(1, 0, half, a, b, f);
    }

    void print() const
    {
        // cout << "#VALUE" << endl;
        // for (int i = half; i < size; i++) {
        //     cout << value[i] << " ";
        // }
        // cout << endl;
        // cout << "#ACTION" << endl;
        // for (int i = 1; i < half; i++) {
        //     cout << action[i] << " ";
        // }
        // cout << endl;
    }

private:
    void modifyRec(const int int_index, const int int_left, const int int_right, const int mod_left, const int mod_right, const F& f)
    {
        if (mod_left <= int_left and int_right <= mod_right) {
            value[int_index] = act(f, value[int_index]);
            action[int_index] = compose(f, action[int_index]);
        } else if (int_right <= mod_left or mod_right <= int_left) {
            // Do nothing
        } else {
            modifyRec(2 * int_index, int_left, (int_left + int_right) / 2, 0, half, action[int_index]);
            modifyRec(2 * int_index, int_left, (int_left + int_right) / 2, mod_left, mod_right, f);
            modifyRec(2 * int_index + 1, (int_left + int_right) / 2, int_right, 0, half, action[int_index]);
            modifyRec(2 * int_index + 1, (int_left + int_right) / 2, int_right, mod_left, mod_right, f);
            value[int_index] = acc(value[2 * int_index], value[2 * int_index + 1]);
            action[int_index] = OpMonoid::identity();
        }
    }

    T accumulateRec(const int int_index, const int int_left, const int int_right, const int mod_left, const int mod_right) const
    {
        if (mod_left <= int_left and int_right <= mod_right) {
            return value[int_index];
        } else if (int_right <= mod_left or mod_right <= int_left) {
            return AccMonoid::identity();
        } else {
            return act(action[int_index], acc(accumulateRec(2 * int_index, int_left, (int_left + int_right) / 2, mod_left, mod_right),
                                              accumulateRec(2 * int_index + 1, (int_left + int_right) / 2, int_right, mod_left, mod_right)));
        }
    }

    const int data_num;  // Num of valid data on leaves.
    const int height;
    const int size;
    const int half;
    vector<T> value;   // Tree for value(length: size)
    vector<F> action;  // Tree for action(length: half)
    bool has_lazy;

    const AccMonoid acc{};
    const OpMonoid compose{};
    const BaseAlgebra act{};
};
struct Max_Plus {
    using T = ll;

    struct AccMonoid {
        T operator()(const T& a, const T& b) const { return max(a, b); }
        static constexpr T identity() { return -INF; }
    };

    struct OpMonoid {
        using T = ll;
        T operator()(const T& f1, const T& f2) const { return f1 + f2; }
        static constexpr T identity() { return 0; }
    };

    T operator()(const OpMonoid::T& f, const T& x) const { return f + x; }
};

struct Graph {
    Graph(const int n)
    {
        edge.resize(n);
    }
    void addEdge(const int from, const int to)
    {
        edge[from].push_back(to);
    }
    vector<vector<int>> edge;
};

constexpr ll MOD = (ll)(1e9 + 7);
constexpr ll PNUM = 12;
constexpr ll prime[PNUM] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};

ll power(const ll p, const ll n)
{
    if (n == 0) {
        return 1;
    }
    if (n % 2 == 1) {
        return (power(p, n - 1) * p) % MOD;
    } else {
        const ll pp = power(p, n / 2);
        return (pp * pp) % MOD;
    }
}

int main()
{
    ll N, Q;
    cin >> N >> Q;
    vector<ll> p(N);
    for (ll i = 0; i < N; i++) {
        cin >> p[i];
        p[i]--;
    }
    Graph g(N);
    for (int i = 0; i < N; i++) {
        g.addEdge(i, p[i]);
    }
    vector<ll> size;
    vector<ll> comp(N, 0);
    vector<bool> used(N, false);
    ll com = 0;
    for (int i = 0; i < N; i++) {
        if (used[i]) {
            continue;
        }
        ll cnt = 0;
        ll pos = i;
        for (;; cnt++) {
            if (used[pos]) {
                break;
            }
            comp[pos] = com;
            used[pos] = true;
            pos = g.edge[pos][0];
        }
        com++;
        size.push_back(cnt);
    }
    vector<ll> lcm(PNUM, 0);
    vector<vector<ll>> index(com, vector<ll>(PNUM, 0));
    for (ll j = 0; j < com; j++) {
        ll num = size[j];
        for (int i = 0; i < PNUM; i++) {
            ll a = 0;
            while (num % prime[i] == 0) {
                a++;
                num /= prime[i];
            }
            index[j][i] = a;
            lcm[i] = max(lcm[i], a);
        }
    }

    vector<SegmentTree<Max_Plus>> segs(PNUM, SegmentTree<Max_Plus>(N));
    for (ll i = 0; i < N; i++) {
        for (ll k = 0; k < PNUM; k++) {
            segs[k].set(i, index[comp[i]][k]);
        }
    }

    vector<ll> cycle(com, 0);
    for (ll i = 0; i < com; i++) {
        ll num = 1;
        for (ll j = 0; j < PNUM; j++) {
            num = (num * power(prime[j], lcm[j] - index[i][j])) % MOD;
        }
        cycle[i] = num;
    }
    vector<ll> sum(com, 0);
    for (ll i = 0; i < N; i++) {
        sum[comp[i]] += (i + 1);
    }

    vector<ll> imos(N, 0);
    for (ll i = 0; i < N; i++) {
        imos[i] += (sum[comp[i]] * cycle[comp[i]]) % MOD;
    }
    for (ll i = 1; i < N; i++) {
        imos[i] += imos[i - 1];
        imos[i] %= MOD;
    }

    for (ll q = 0; q < Q; q++) {
        ll l, r;
        cin >> l >> r;
        l--, r--;
        const ll v = (imos[r] - ((l >= 1) ? imos[l - 1] : 0) + MOD) % MOD;
        ll prod = 1;
        for (ll k = 0; k < PNUM; k++) {
            const ll ind = segs[k].accumulate(l, r + 1);
            prod = (prod * power(prime[k], lcm[k] - ind)) % MOD;
        }
        const ll inv = power(prod, MOD - 2);
        cout << (v * inv) % MOD << endl;
    }


    return 0;
}

Measured memory_bytes: 63868