#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using vi = vector<int>;    using vvi = vector<vi>;
using vb = vector<bool>;   using vvb = vector<vb>;
using vl = vector<ll>;     using vvl = vector<vl>;
using vd = vector<double>; using vvd = vector<vd>;

#define REP(i,n) for(ll i = 0; i < (n); ++i)
#define ALL(c) (c).begin(), (c).end()
#define FOR(i,s,e) for (ll i = s; i < (ll)e; i++)
#define TEN(x) ((ll)1e##x)


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

template<ll mod> struct GF {
	ll v;
	GF(ll v = 0) : v((v % mod + mod) % mod) {}
	GF operator+(GF x) const { return v + x.v; }
	GF operator-(GF x) const { return v - x.v; }
	GF operator*(GF x) const { return v * x.v; }
	GF operator/(GF x) const { return x.inverse() * v; }
	GF operator+=(GF x) { return (*this) = (*this) + x; }
	GF operator*=(GF x) { return (*this) = (*this) * x; }
	GF operator-=(GF x) { return (*this) = (*this) - x; }
	GF operator/=(GF x) { return (*this) = (*this) / x; }
	GF inverse() { // http://topcoder.g.hatena.ne.jp/iwiwi/20130105/1357363348
		ll a = v, b = mod, x = 1, y = 0;
		while (b) {
			ll t = a / b;
			swap(a -= t * b, b);
			swap(x -= t * y, y);
		}
		return x;
	}
};

template <typename Traits>
class SegmentTree {
public:
	typedef typename Traits::value_type value_type;

private:
	Traits traits;
	vector<value_type> data;
	size_t size;

	void initialize() {
		if (size < 2) return;
		for (auto i = size - 2;; --i) {
			data[i] = traits(data[i * 2 + 1], data[i * 2 + 2]);
			if (i == 0) break;
		}
	}

	// [a,b)???????????????????????±???
	// k     : ?????¨??????????????\????????????
	// [l,r) : k????????????????????? 
	value_type query(size_t a, size_t b, size_t k, size_t l, size_t r) const {
		if (r <= a || b <= l) return traits.default_value(); //?????????
		if (a <= l && r <= b) return data[k];                //[l,r) ??? [a,b)

															 //[l,r)????????¨???[a,b)???????????????
		const value_type & vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
		const value_type & vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
		return traits(vl, vr);
	}

public:
	explicit SegmentTree(size_t n = 0, const Traits &traits = Traits())
		: size(1), traits(traits)
	{
		while (size < n) size *= 2;
		data.assign(size * 2 - 1, traits.default_value());
		initialize();
	}
	template <typename Iterator>
	SegmentTree(
		Iterator first, Iterator last, const Traits &traits = Traits()
	) : size(1), traits(traits) {
		const size_t n = distance(first, last);
		while (size < n) size *= 2;
		data.resize(size * 2 - 1, traits.default_value());
		copy(first, last, data.begin() + size - 1);
		initialize();
	}
	void update(size_t i, const value_type &val) {
		i += size - 1; // segment tree??????index?????????
		data[i] = val;
		while (i > 0) {
			i = (i - 1) / 2;
			data[i] = traits(data[i * 2 + 1], data[i * 2 + 2]);
		}
	}
	value_type query(size_t a, size_t b) const { return query(a, b, 0, 0, size); }
	value_type query() const { return query(0, size); }
	value_type operator[](size_t i) const { return data[size - 1 + i]; }
};

const ll mod = TEN(9) + 7;

template <typename T>
struct SumSegmentTreeTraits {
	typedef T value_type;
	T default_value() const { return 0; }
	T operator()(const T &a, const T &b) const { return a + b; }
};

template <typename T>
struct LCM_SegmentTreeTraits {
	typedef T value_type;
	T default_value() const { return 1; }
	T operator()(const T &a, const T &b) const { return lcm(a, b); }
};

int main() {
#ifdef INPUT_FROM_FILE
	ifstream cin("sample.in");
	ofstream cout("sample.out");
#endif
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(50);

	ll n, q; cin >> n >> q;
	vl p(n);
	REP(i, n) cin >> p[i];
	REP(i, n) p[i]--;

	const auto seg_lcm = [&] {
		vl cnt(n, 0);
		REP(i, n) {
			ll index = i;
			while (true) {
				cnt[i]++;
				if (p[index] == i) break;
				index = p[index];
			}
		}
		return SegmentTree<LCM_SegmentTreeTraits<ll>>(ALL(cnt));
	}();
	auto all_lcm = seg_lcm.query();

	const auto seg_sum = [&] {
		vector<GF<mod>> cnt(n, 0);
		REP(i, n) {
			ll index = i;
			while (true) {
				cnt[i] += index + 1;
				if (p[index] == i) break;
				index = p[index];
			}
			cnt[i] *= all_lcm / seg_lcm[i];
		}
		return SegmentTree<SumSegmentTreeTraits<GF<mod>>>(ALL(cnt));
	}();

	REP(i, q) {
		ll l, r; cin >> l >> r;
		auto times = seg_lcm.query(l - 1, r);
		cout << (seg_sum.query(l - 1, r) * times / all_lcm).v << endl;
	}

	return 0;
}

Measured memory_bytes: 8544