Newcoder 40 F.珂朵莉的約數(數論+莫隊演算法)
阿新 • • 發佈:2018-11-02
Description
珂朵莉給你一個長為 的序列,有 次查詢
每次查詢給兩個數
設 為區間 內所有數的乘積
求 的約數個數
Input
第一行兩個正整數
第二行一個長為 的序列
之後 行每行兩個數 和
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
對於不超過 的素數直接維護每個素數的冪指數 的字首乘積即可(共 個),而每個數超過 的素因子至多一個,這部分用莫隊維護下區間這些素因子的冪指數 的乘積即可,此處需要線性預處理逆元,時間複雜度
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;
}