题意:给出n个数n (1 ≤ n ≤ 106): x1, x2, ..., xn (2 ≤ xi ≤ 107).
然后m (1 ≤ m ≤ 50000)次查询, [Li, Ri] ;输出每次Li与Ri之间所有素数的P值之和。每个素数的p值的定义是这样的:P(x)表示在给出的n个数里面有多少个数是x的整数倍数。
解法:在线性筛素数的时候,把每个素数的P值可以直接顺便算出来,然后求个前缀和,
查询的时候就变成O(1)了,复杂度取决于线性的筛素数。
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
long long num[10000100];
long long ans[10000100];
bool rem[10000010];
int n;
int m;
int main()
{
scanf("%d",&n);
memset(num,0,sizeof num);
for(int i=0;i<n;i++)
{
int a;
scanf("%d",&a);
num[a]++;
}
for(int i=2;i<=10000000;i++)
if(!rem[i])
{
ans[i]+=num[i];
for(int j=i*2;j<=10000000;j+=i)
{
rem[j]=true;
ans[i]+=num[j];if(i==3&&num[j]!=0);
}
}
for(int i=1;i<=10000000;i++)
ans[i]=ans[i]+ans[i-1];
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a>10000000)
printf("0\n");
else
printf("%d\n",ans[min(10000000,b)]-ans[a-1]);
}
return 0;
}