NC14833. 珂朵莉的约数
描述
珂朵莉给你一个长为n的序列,有m次查询
每次查询给两个数l,r
设s为区间[l,r]内所有数的乘积
求s的约数个数mod 1000000007
输入描述
第一行两个正整数n,m
第二行一个长为n的序列
之后m行每行两个数l和r
输出描述
对于每个询问,输出一个整数表示答案
示例1
输入:
5 5 64 2 18 9 100 1 5 2 4 2 3 1 4 3 4
输出:
165 15 9 45 10
C++ 解法, 执行用时: 606ms, 内存消耗: 74192K, 提交时间: 2022-03-10 15:47:42
#include<bits/stdc++.h> #define For(i,a,b) for(int i=(a),_en=(b);i<=_en;i++) #define M 100005 #define mod 1000000007 using namespace std; int a[M],y[M][170],n,m,S,l=1,r,res=1; int ans[M],q[10*M],yz[M],cnt,ni[M]; bool mk[M]; struct name{ int l,r,id; bool operator <(const name &_)const{ if (l/S!=_.l/S) return l<_.l; if ((l/S)&1) return r>_.r; return r<_.r; } }Q[M]; void init(){ ni[1]=ni[0]=1;S=sqrt(n); For(i,2,1000){ if(mk[i])continue; yz[cnt++]=i; for(int j=i*2;j<=1000;j+=i)mk[j]=1; } For(i,2,n)ni[i]=1ll*(mod-mod/i)*ni[mod%i]%mod; } void add(int x){ if(a[x]==1)return; res=1ll*res*ni[q[a[x]]+1]%mod; q[a[x]]++; res=1ll*res*(q[a[x]]+1)%mod; } void del(int x){ if(a[x]==1)return; res=1ll*res*ni[q[a[x]]+1]%mod; q[a[x]]--; res=1ll*res*(q[a[x]]+1)%mod; } int main(){ scanf("%d%d",&n,&m);init(); For(i,1,n){ int x; scanf("%d",&x); For(j,0,167){ y[i][j]+=y[i-1][j]; while(!(x%yz[j])){ x/=yz[j]; y[i][j]++; } } a[i]=x; } For(i,1,m){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; } sort(Q+1,Q+m+1); For(i,1,m){ while(l>Q[i].l)add(--l); while(r<Q[i].r)add(++r); while(l<Q[i].l)del(l++); while(r>Q[i].r)del(r--); int ANS=1; For(j,0,167) ANS=1ll*ANS*(y[r][j]-y[l-1][j]+1)%mod; ans[Q[i].id]=1ll*res*ANS%mod; } For(i,1,m)printf("%d\n",ans[i]); return 0; }