#include <iostream>
using namespace std;
using ll = long long;
// 常量定义:N为数组最大长度,M为模数(1e9+7是质数,满足费马小定理条件)
const ll N = 1e5 + 5, M = 1e9 + 7;
ll a[N]; // 存储原始数组
ll f[N]; // 存储前缀积数组,f[i] = a[1]*a[2]*...*a[i] mod M
/**
* 快速幂算法(二分幂)
* 算法思想:将幂运算拆解为二进制形式,通过二分思想降低时间复杂度(O(log power))
* 功能:计算 (base^power) % M,用于求模运算下的乘法逆元
* @param base 底数
* @param power 指数
* @return 计算结果 mod M
*/
ll qpow(ll base, ll power) { // 传入base=3,power=5
ll res = 1; // 结果初始化为1(乘法的“单位元”,就像加法初始化为0一样)
while (power) { // 只要指数power>0,就继续循环(此时power=5→2→1→0)
// 第一步:判断当前指数的二进制最后一位是不是1
if (power &
1) { // power&1 是二进制运算,等价于“power%2==1”(判断奇偶)
// 如果是1,就把当前的底数乘到结果里(并取模防止溢出)
res = (res * base) % M; // 我们例子里的变化:
// 第一次循环(power=5):res=1*3=3
// 第二次循环(power=2):power&1=0,跳过
// 第三次循环(power=1):res=3*9=27(最终3^5=27)
}
// 第二步:底数平方(对应指数折半)
base = (base * base) % M; // 例子里的变化:
// 第一次循环:base=3*3=9(对应3^2)
// 第二次循环:base=9*9=81(对应3^4)
// 第三次循环:base=81*81=6561(对应3^8)
// 第三步:指数右移一位(等价于power=power/2,向下取整)
power >>= 1; // 例子里的变化:
// 第一次循环:5>>1=2(二进制101→10)
// 第二次循环:2>>1=1(二进制10→1)
// 第三次循环:1>>1=0(二进制1→0,循环结束)
}
return res; // 返回27,也就是3^5的结果
}
int main() {
// 关闭同步流,加速cin/cout输入输出(算法优化步骤)
ios::sync_with_stdio(0), cin.tie(0);
ll n, q; // n为数组长度,q为查询次数
cin >> n >> q;
// 步骤1:初始化前缀积数组(空乘积为1,乘法单位元)
f[0] = 1;
// 步骤2:预处理前缀积数组
// 算法思想:前缀积可以将区间[l,r]的乘积转化为 f[r]/f[l-1],降低查询时间复杂度
for (ll i = 1; i <= n; i++) {
cin >> a[i];
// 前缀积递推公式:当前前缀积 = 前一个前缀积 * 当前元素 mod M(防止数值溢出)
f[i] = (f[i - 1] * a[i]) % M;
}
// 步骤3:处理每次查询
while (q--) {
ll l, r; // 查询区间[l,r]
cin >> l >> r;
// 核心算法思想:模运算中除法不能直接计算,需用乘法逆元替代
// 费马小定理:若M是质数,a的逆元为 a^(M-2) mod M
// 区间[l,r]乘积 = (f[r] * 逆元(f[l-1])) mod M
cout << (f[r] * qpow(f[l - 1], M - 2)) % M << " ";
}
return 0;
}