1. 程式人生 > >Newcoder 40 F.珂朵莉的約數(數論+莫隊演算法)

Newcoder 40 F.珂朵莉的約數(數論+莫隊演算法)

Description

珂朵莉給你一個長為 n n 的序列,有 m m 次查詢

每次查詢給兩個數 l ,

r l,r

s s 為區間 [ l , r

] [l,r] 內所有數的乘積

s s 的約數個數 m o d

  1000000007 mod\ 1000000007

Input

第一行兩個正整數 n , m n,m

第二行一個長為 n n 的序列

之後 m m 行每行兩個數 l l r r

( n , m 1 0 5 , a i 1 0 6 ) (n,m\le 10^5,a_i\le 10^6)

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 的素數直接維護每個素數的冪指數 + 1 +1 的字首乘積即可(共 168 168 個),而每個數超過 1000 1000 的素因子至多一個,這部分用莫隊維護下區間這些素因子的冪指數 + 1 +1 的乘積即可,此處需要線性預處理逆元,時間複雜度 O ( n n + 168 m ) O(n\sqrt{n}+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;
}