分析
考虑莫队。
令 S = lcm ( a l , a l + 1 , a l + 2 , … , a r − 1 ) S=\operatorname{lcm}(a_l,a_{l+1},a_{l+2},\dots,a_{r-1}) S=lcm(al,al+1,al+2,…,ar−1)。则对于新加进来的 a r a_r ar,有:
lcm ( a l , a l + 1 , a l + 2 , … , a r − 1 , a r ) = lcm ( S , a r ) = S × a r gcd ( S , a r ) \operatorname{lcm}(a_l,a_{l+1},a_{l+2},\dots,a_{r-1},a_r)\\=\operatorname{lcm}(S,a_r)\\=\frac{S \times a_r}{\gcd(S,a_r)} lcm(al,al+1,al+2,…,ar−1,ar)=lcm(S,ar)=gcd(S,ar)S×ar
很容易发现, S S S 在不取模的情况下会爆 __int128,所以不能这么搞。
考虑从 a r a_r ar 对 lcm ( a l , a l + 1 , a l + 2 , … , a r − 1 , a r ) \operatorname{lcm}(a_l,a_{l+1},a_{l+2},\dots,a_{r-1},a_r) lcm(al,al+1,al+2,…,ar−1,ar) 的贡献。 令 a r a_r ar 的贡献为 b r b_r br,则:
b r = a r gcd ( ∏ i = l r − 1 b i , a r ) b_r = \frac{a_r}{\gcd(\prod \limits_{i=l}^{r-1}b_i ,a_r)} br=gcd(i=l∏r−1bi,ar)ar
然后答案就是 ∏ i = l r b i \prod \limits_{i=l}^{r} b_i i=l∏rbi。
删除不好搞,用回滚即可。复杂度是 O ( T n 2 n ) O(T n^2 \sqrt{n}) O(Tn2n) 的。
【关于卡常】
注意到 gcd ( a , b ) = gcd ( a m o d b , b ) \gcd(a,b)=\gcd(a \bmod b,b) gcd(a,b)=gcd(amodb,b)。那么在算 ∏ i = l r − 1 b i \prod \limits_{i=l}^{r-1}b_i i=l∏r−1bi 的时候,我们就可以将其对 a r a_r ar 取模,保证乘积不会爆 longlong。
在暴力求乘积的时候,如果当前的乘积是 a r a_r ar 的倍数,直接退出循环即可。在正常卡常的基础上加上这个就能过了。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define il inline
#define pii pair<int,int>
#define x first
#define y second
#define gc getchar()
#define rd read()
#define debug() puts("------------")
namespace yzqwq{
il ll read(){
ll x=0;
int f=1;char ch=gc;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc;}
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=gc;
return x*f;
}
il int qmi(int a,int b,int p){
int ans=1;
while(b){
if(b&1) ans=ans*a%p;
a=a*a%p,b>>=1;
}
return ans;
}
il auto max(auto a,auto b){return (a>b?a:b);}
il int min(int a,int b){return (a<b?a:b);}
il ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}
il int lcm(int a,int b){
return a/gcd(a,b)*b;
}
il void exgcd(int a,int b,int &x,int &y){
if(!b) return x=1,y=0,void(0);
exgcd(b,a%b,x,y);
int t=x;
x=y,y=t-a/b*x;
return ;
}
mt19937 rnd(time(0));
}
using namespace yzqwq;
const int N=305;
const ll p=1e9+7;
struct node{
int l,r,id;
}Q[N];
int n,q,len;
ll a[N],ans[N];
ll b_[N],b[N];
ll S,S_,s;
il int get(int x){
return (x-1)/len+1;
}
il bool cmp(node a,node b){
if((a.l-1)/len!=(b.l-1)/len) return a.l<b.l;
return a.r<b.r;
}
ll mul(ll a,ll b,ll m){
ll t=a*b-(ll)((long double)a/m*b)*m;
return t<0?t+m:(t>=m?t-m:t);
}
il void solve(){
n=rd,q=rd,len=sqrt(n),S=1;
for(re int i=1;i<=n;++i) a[i]=rd;
for(re int i=1;i<=q;++i) Q[i]={rd,rd,i};
sort(Q+1,Q+q+1,cmp);
int l=1,l_,r=0,lst_bk=0;
for(re int i=1;i<=q;++i){
if(get(Q[i].l)==get(Q[i].r)){
S_=1;
for(re int j=Q[i].l;j<=Q[i].r;++j){
s=1;
for(re int k=Q[i].l;k<j;++k){
s=mul(s,b_[k],a[j]);
if(!s) break;
}
b_[j]=a[j]/gcd(a[j],s);
S_=(S_*(b_[j]%p))%p;
}
ans[Q[i].id]=S_;
continue;
}
if(lst_bk!=get(Q[i].l)){
lst_bk=get(Q[i].l);
l=min(lst_bk*len,n)+1,r=l-1;
S=1;
}
while(r<Q[i].r){
++r,s=1;
for(re int k=l;k<r;++k){
s=mul(s,b[k],a[r]);
if(!s) break;
}
b[r]=a[r]/gcd(a[r],s);
S=(S*(b[r]%p))%p;
}
S_=S,l_=l;
while(l_>Q[i].l){
--l_,s=1;
for(re int k=l_+1;k<=r;++k){
s=mul(s,b[k],a[l_]);
if(!s) break;
}
b[l_]=a[l_]/gcd(a[l_],s);
S_=(S_*(b[l_]%p))%p;
}
ans[Q[i].id]=S_;
}
for(re int i=1;i<=q;++i) printf("%lld\n",ans[i]);
return ;
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int t=rd;while(t--)
solve();
return 0;
}