Description
珂朵莉给你一个长为 n n n的序列,有 m m m次查询
每次查询给两个数 l , r l,r l,r
设 s s s为区间 [ l , r ] [l,r] [l,r]内所有数的乘积
求 s s s的约数个数 m o d 1000000007 mod\ 1000000007 mod 1000000007
Input
第一行两个正整数 n , m n,m n,m
第二行一个长为 n n n的序列
之后 m m m行每行两个数 l l l和 r r r
( n , m ≤ 1 0 5 , a i ≤ 1 0 6 ) (n,m\le 10^5,a_i\le 10^6) (n,m≤105,ai≤106)
Output
对于每个询问,输出一个整数表示答案
Sample Input
5 5
64 2 18 9 100
1 5
2 4
2 3
1 4
3 4
Sample Output
165
15
9
45
10
Solution
对于不超过 1000 1000 1000的素数直接维护每个素数的幂指数 + 1 +1 +1的前缀乘积即可(共 168 168 168个),而每个数超过 1000 1000 1000的素因子至多一个,这部分用莫队维护下区间这些素因子的幂指数 + 1 +1 +1的乘积即可,此处需要线性预处理逆元,时间复杂度 O ( n n + 168 m ) O(n\sqrt{n}+168m) O(nn+168m)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
#define mod 1000000007
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
struct node
{
int l,r,id,ans;
}q[maxn];
int n,m,c[maxn],pos[maxn],ans;
int cmp1(node x,node y)
{
if(pos[x.l]!=pos[y.l])return x.l<y.l;
return x.r<y.r;
}
int cmp2(node x,node y)
{
return x.id<y.id;
}
int p[maxn],res,mark[maxn];
void init(int n=1000)
{
for(int i=2;i<=n;i++)
if(!mark[i])
{
p[res++]=i;
for(int j=2*i;j<=n;j+=i)mark[j]=1;
}
}
int num[1000005],inv[1000005],f[170][maxn];
void deal(int x,int id)
{
for(int i=0;i<res;i++)f[i][id]=f[i][id-1];
for(int i=0;i<res;i++)
{
if(x<p[i])break;
while(x%p[i]==0)x/=p[i],f[i][id]++;
}
c[id]=x;
}
void update(int x,int v)//表示对第x个元素做删除(v=-1)或者添加(v=1)
{
if(c[x]==1)return ;
ans=mul(ans,inv[num[c[x]]+1]);
num[c[x]]+=v;
ans=mul(ans,num[c[x]]+1);
}
int main()
{
init(1000);
inv[1]=1;
for(int i=2;i<=1e6+1;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
scanf("%d%d",&n,&m);
int mm=(int)sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
deal(c[i],i);
pos[i]=(i-1)/mm+1;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
q[i].ans=1;
for(int j=0;j<res;j++)q[i].ans=mul(q[i].ans,f[j][q[i].r]-f[j][q[i].l-1]+1);
}
sort(q,q+m,cmp1);
ans=1;
int l=1,r=0;
for(int i=0;i<m;i++)
{
while(r<q[i].r)update(r+1,1),r++;
while(r>q[i].r)update(r,-1),r--;
while(l<q[i].l)update(l,-1),l++;
while(l>q[i].l)update(l-1,1),l--;
q[i].ans=mul(q[i].ans,ans);
}
sort(q,q+m,cmp2);
for(int i=0;i<m;i++)printf("%d\n",q[i].ans);
return 0;
}