#include <bits/stdc++.h>
using namespace std;
#define FOR(i,k,n) for(int i = (k); i < (n); i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(a) a.begin(), a.end()
#define MS(m,v) memset(m,v,sizeof(m))
#define D10 fixed<<setprecision(10)
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<ll, ll> pii;
const ll MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template<class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/

ll gcd(ll a, ll b)
{
	if (a < b) swap(a, b);
	return (a%b ? gcd(a%b, b) : b);
}

ll lcm(ll a, ll b)
{
	return a / gcd(a, b)*b;
}

struct Data
{
	pair<ll, ll> num;
	Data() :num(pii(1, 0)) {};
	Data(ll n, ll m) :num(pii(n, m)) {};
};

ll tlcm;

struct SegmentTree
{
	int n; vector<Data> data;
	SegmentTree(int N)
	{
		n = 1;
		while (n < N) n *= 2;
		data.resize(2 * n);
	}
private:
	ll sub(int left, int right, int node, int nleft, int nright)
	{
		if (nright <= left || right <= nleft) return 0;
		if (left <= nleft && nright <= right) return ((tlcm / data[node].num.first)%MOD*data[node].num.second) % MOD;
		ll vl = sub(left, right, node * 2 + 1, nleft, (nleft + nright) / 2);
		ll vr = sub(left, right, node * 2 + 2, (nleft + nright) / 2, nright);
		vl %= MOD; vr %= MOD;
		return (vl + vr) % MOD;;
	}

	ll seglcm(int left, int right, int node, int nleft, int nright)
	{
		if (nright <= left || right <= nleft) return 1;
		if (left <= nleft && nright <= right) return data[node].num.first;
		ll vl = seglcm(left, right, node * 2 + 1, nleft, (nleft + nright) / 2);
		ll vr = seglcm(left, right, node * 2 + 2, (nleft + nright) / 2, nright);
		return lcm(vl, vr);
	}

public:
	void update(int pos, Data value)
	{
		pos += n - 1;
		data[pos] = value;
		while (pos > 0)
		{
			pos = (pos - 1) / 2;
			data[pos].num.first = lcm(data[pos * 2 + 1].num.first, data[pos * 2 + 2].num.first);
			ll l = (data[pos].num.first / data[pos * 2 + 1].num.first) % MOD * data[pos * 2 + 1].num.second;
			ll r = (data[pos].num.first / data[pos * 2 + 2].num.first) % MOD * data[pos * 2 + 2].num.second;
			assert(!(l < 0 || r < 0));
			l %= MOD, r %= MOD;
			data[pos].num.second = (l + r) % MOD;
		}
	}
	ll sum_query(int left, int right)
	{
		tlcm = seglcm(left, right, 0, 0, n);
		return sub(left, right, 0, 0, n);
	}
};

struct UnionFind
{
	vector<pair<long long, long long>> par;
	UnionFind(int n) 
	{
		REP(i, n) par.emplace_back(-i, 1); 
	}
	int find(int x) { return par[x].first < 0 ? x : par[x].first = find(par[x].first); }
	void unite(int x, int y)
	{
		x = find(x); y = find(y);
		if (x == y) return;
		par[x].first += par[y].first;
		par[x].second += par[y].second;
		par[y].first = x;
		if (find(x) != find(y)) par[find(y)].first = x;
	}
	bool same(int x, int y)
	{
		return find(x) == find(y);
	}
};


int main()
{
	int n, q;
	cin >> n >> q;
	vi v(n);
	REP(i, n) cin >> v[i];
	UnionFind uf(n+1);
	REP(i, n) uf.unite(i + 1, v[i]);
	SegmentTree seg(n);
	REP(i, n)
	{
		int root = uf.find(i + 1);
		long long sum = -uf.par[root].first, cm = uf.par[root].second;
		assert(sum >= 0);
		seg.update(i, Data(cm, sum%MOD));
	}
	REP(i, q)
	{
		int a, b; cin >> a >> b;
		assert(seg.sum_query(a - 1, b) % MOD >= 0);
		cout << seg.sum_query(a - 1, b) % MOD << endl;
	}
	return 0;
}

Measured memory_bytes: 8976