洛谷 P5071 [Ynoi Easy Round 2015] 此时此刻的光辉
令 \(V = 10 ^ 9\),先把 \(\sqrt V\) 内的所有质数筛出来,然后对每个 \(a _ i\) 分解质因数,所有不同的质因数只有 \(\text O (\sqrt V + n)\) 个。
考虑莫队,由于一个 \(a _ i\) 只有不超过 \(10\) 个不同的质因数,所以加入和删除是常数级别的。由于还有除法,每次答案的分子和分母分开维护,查询时再除一下。
时间复杂度 \(\text O (nm + 10 n \sqrt q + q \log V)\),其中 \(m\) 是 \(\sqrt V\) 内质数的个数。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#define N 100005
using namespace std;
const int mod=19260817,V=1e9,S=sqrt(V);
int n,q,a[N],ans[N];
int cnt,cc,p[N],D[N];
map<int,int> id;
void sieve(int n) {
for(int i=2;i<=n;i++) {
if(!D[i]) p[++cnt]=i,D[i]=cnt;
for(int j=1;j<=cnt&&p[j]<=n/i;j++) {
D[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
struct pr {
int p,c;
pr() {}
pr(int u,int v) {p=u,c=v;}
};
vector<pr> d[N];
vector<pr> divide(int x) {
vector<pr> res;
for(int i=1;i<=cnt&&p[i]<=x/p[i];i++) {
if(x%p[i]==0) {
int c=0;
while(x%p[i]==0) c++,x/=p[i];
res.emplace_back(i,c);
}
}
if(x>1) {
if(x<=S) res.emplace_back(D[x],1);
else {
if(!id.count(x)) id[x]=++cc;
res.emplace_back(id[x],1);
}
}
return res;
}
struct que {
int l,r,id;
} b[N];
int l,r,up,dn,vis[N*2];
int qpow(long long x,int y) {
int res=1;
for(;y;y>>=1) {
if(y&1) res=res*x%mod;
x=x*x%mod;
}
return res;
}
int inv(int x) {
return qpow(x,mod-2);
}
void ins(int x,int op) {
for(auto u:d[x]) dn=1ll*dn*vis[u.p]%mod;
for(auto u:d[x]) vis[u.p]+=op*u.c,up=1ll*up*vis[u.p]%mod;
}
int main() {
scanf("%d%d",&n,&q);
sieve(S),cc=cnt;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),d[i]=divide(a[i]);
for(int i=1;i<=q;i++) scanf("%d%d",&b[i].l,&b[i].r),b[i].id=i;
int B=max(n/sqrt(q),1.0);
sort(b+1,b+q+1,[&](que x,que y)->bool {
if((x.l-1)/B!=(y.l-1)/B) return (x.l-1)/B<(y.l-1)/B;
return (x.l-1)/B&1?x.r>y.r:x.r<y.r;
});
l=1,r=0,up=dn=1,fill(vis+1,vis+cc+1,1);
for(int i=1;i<=q;i++) {
while(r<b[i].r) ins(++r,1); while(l>b[i].l) ins(--l,1);
while(r>b[i].r) ins(r--,-1); while(l<b[i].l) ins(l++,-1);
ans[b[i].id]=1ll*up*inv(dn)%mod;
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号