题意:
N个数 每个数x[i]对能整除的素数p贡献1 (即p得一分) M个询问 每个询问输出[L,R]区间内所有素数的得分之和
思路:
数据这么大明显离线处理M个询问 将N个数字的素数因子全都找出来并计算完贡献得分即可简化处理询问
综上思路及x[i]的大小可知必须先打素数表 然后枚举N个数 找出所有素数因子 计算贡献得分
最后每个询问[L,R]就是 sum(R) - sum(0,L-1)
本题我用了树状数组 不过没什么必要 我单纯为了敲一边代码玩… - -b
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 10000010
int n,m,cnt=1;
int flag[M],c[M],p[M];
int lowbit(int fa)
{
return fa&(-fa);
}
void add(int fa)
{
while(fa<M)
{
c[fa]++;
fa+=lowbit(fa);
}
}
int query(int fa)
{
int tmp=0;
while(fa)
{
tmp+=c[fa];
fa-=lowbit(fa);
}
return tmp;
}
void get_prime()
{
int i,j;
for(i=2;i<M;i++)
{
if(!flag[i]) p[cnt++]=i;
for(j=1;j<cnt&&p[j]*i<M;j++)
{
flag[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
int main()
{
int i,j,x;
scanf("%d",&n);
get_prime();
for(i=0;i<n;i++)
{
scanf("%d",&x);
for(j=1;flag[x];j++)
{
if(x%p[j]==0) add(p[j]);
while(x%p[j]==0) x/=p[j];
}
if(x!=1) add(x);
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&i,&j);
i=min(i,M-10);
j=min(j,M-10);
printf("%d\n",query(j)-query(i-1));
}
return 0;
}