题意:n个数,m次询问,每次询问给出[li,ri],S[li,ri]为li~ri的素数,f(p) ai满足p|ai的个数,问segma(p∈S[li,ri]) f(p)的值?
n<=1e6 m<=5e5 先标记ai后 根据素因子筛法思想,更新F(p) =cnt[p]+cnt[2p]+..cnt[kp]
接下来只要快速求出 f[li~ri]的和,利用前缀和即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+20;
int n,m,a[N],pri[N],vis[N],pn=0,cnt[N];
ll f[N];// f(p) ai满足p|ai的个数
void get_prime()//ai<=1e7
{
memset(vis,-1,sizeof(vis));
for(int i=2;i<N;i++)
{
if(vis[i]==-1)
{
pri[++pn]=i;
for(int j=i+i;j<N;j+=i)
vis[j]=1;
}
}
}
void update()
{
//f[i] i不是素数不会被更新
for(int i=1;i<=pn;i++)
{
for(int j=pri[i];j<N;j+=pri[i])
{
f[pri[i]]+=cnt[j];
}
}
}
int main()
{
get_prime();//
while(cin>>n)
{
memset(f,0,sizeof(f));
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
}
update();//NlogN
for(int i=1;i<N;i++)
f[i]=f[i]+f[i-1];
cin>>m;
while(m--)
{
ll l,r,inf=1e7;
scanf("%I64d%I64d",&l,&r);
l=min(l,inf);// xi<=1e7 p|xi p>1e7 f(p)=0
r=min(r,inf);
printf("%I64d\n",f[r]-f[l-1]);
}
}
return 0;
}