题解 P5655 【基础数论函数练习题】
orz EMT__Mashiro
通过连续使用
直观的理解就是把
考虑在最右边增加一个
令
意思是说
直接按照这个做,每次令右端点加一,然后算出所有
考虑对每个右端点,不为
令
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500,mod=1000000007;
int T,n,qn;
long long tmp[N],a[N];
int ans[N][N];
long long gcd(long long a,long long b){return b?gcd(b,a%b):a;}
long long mul(long long a,long long b,long long m)
{
long long t=a*b-(long long)((long double)a/m*b)*m;
if(t<0)t+=m;else if(t>=m)t-=m;
return t;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&qn);
for(int i=1;i<=n;i++)
{
scanf("%lld",a+i);
tmp[i]=1;for(int j=i-1;j>=1;j--)tmp[j]=mul(tmp[j+1],a[j],a[i]);
long long t=gcd(tmp[1],a[i]);
for(int j=1;j<i;j++)
if(tmp[j+1]%t)
{
long long g=gcd(tmp[j+1],t);
a[j]/=t/g,t=g;
}
ans[i][i]=a[i]%mod;
for(int j=i-1;j>=1;j--)ans[j][i]=1ll*ans[j+1][i]*((a[j]%mod))%mod;
}
for(int i=1,l,r;i<=qn;i++)
{
scanf("%d%d",&l,&r),printf("%d\n",ans[l][r]);
}
}
}