类似 ‘HH的项链’ 的做法,
将所有询问离线, 按 右端点 从小到大 排序, 然后 从左向右 枚举 ,
首先对当前位置的 进行 质因数 分解, 记 表示 这个因子在 前面最晚出现的位置,
使用 树状数组 维护 前缀积, 若 含有质因子 , 则对 位置上的值 除 , 使 , 最后在 位置上 乘 次 ,
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
int N;
int M;
int pcnt;
int p[maxn];
int A[maxn];
int fm[maxn];
int Ans[maxn];
int last[maxn];
bool vis[maxn];
void sieve(){
for(reg int i = 2; i < maxn; i ++){
if(!vis[i]) p[++ pcnt] = i, fm[i] = i;
for(reg int j = 1; j <= pcnt && i*p[j] < maxn; j ++){
vis[i*p[j]] = 1; fm[i*p[j]] = p[j];
if(i % p[j] == 0) break ;
}
}
}
int Ksm(int a, int b){int s=1;while(b){ if(b&1)s=1ll*s*a%mod;a=1ll*a*a%mod;b>>=1; }return s;}
struct Que{ int l, r, id; } que[maxn];
struct Bit_Tree{
int v[maxn], lim;
void Add(int k, int x){ while(k<=lim)v[k]=1ll*v[k]*x%mod,k+=k&-k; }
int Query(int k){ if(k<=0) return 1; int s=1; while(k)s=1ll*s*v[k]%mod,k-=k&-k; return s; }
} bit_t;
bool cmp(Que a, Que b){ return a.r < b.r; }
int main(){
sieve();
scanf("%d%d", &N, &M); bit_t.lim = N;
for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]), bit_t.v[i] = 1;
for(reg int i = 1; i <= M; i ++) scanf("%d%d", &que[i].l, &que[i].r), que[i].id = i;
std::sort(que+1, que+M+1, cmp); int t = 1;
for(reg int i = 1; i <= N; i ++){
int x = A[i];
while(x > 1){
int k = 1, p = fm[x];
while(x%p == 0){
x /= p, k *= p;
if(last[k]) bit_t.Add(last[k], Ksm(p, mod-2));
last[k] = i; bit_t.Add(i, p);
}
}
while(i == que[t].r) Ans[que[t].id] = 1ll*bit_t.Query(que[t].r)*Ksm(bit_t.Query(que[t].l-1), mod-2)%mod, t ++;
}
for(reg int i = 1; i <= M; i ++) printf("%d
", Ans[i]);
return 0;
}