SSL2846 2017年11月9日提高组T1 质数(线性筛)

来源:互联网 发布:淘宝网廷长收货 编辑:程序博客网 时间:2024/06/06 19:37

2017年11月9日提高组T1 质数

Description

小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感。小X 认为,质数是一切自然数起源的地方。
在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数字。
但由于小X 对质数的热爱超乎寻常,所以小X 同样喜欢那些虽然不是质数,但却是由两个质数相乘得来的数。
于是,我们定义,一个数是小X 喜欢的数,当且仅当其是一个质数,或是两个质数的乘积。
而现在,小X 想要知道,在L 到R 之间,有多少数是他喜欢的数呢?

Input

第一行输入一个正整数Q,表示询问的组数。
接下来Q 行。包含两个正整数L 和R。保证L≤R。

Output

输出Q 行,每行一个整数,表示小X 喜欢的数的个数。

Sample Input

输入1:
1
1 6

输入2:
10
282 491
31 178
645 856
227 367
267 487
474 697
219 468
582 792
315 612
249 307

输入3:
10
20513 96703
15236 86198
23185 78205
40687 48854
42390 95450
63915 76000
36793 92543
35347 53901
44188 76922
82177 90900
Sample Output

输出1:
5
样例1解释:
6以内的质数有2,3,5,而4=2*2,6=2*3。因此2,3,4,5,6都是小X 喜欢的数,而1 不是。

输出2:
97
78
92
65
102
98
114
90
133
29

输出3:
24413
23001
17784
2669
16785
3833
17712
6028
10442
2734
Hint

这里写图片描述

分析:筛质数,顺便把两个质数乘积标记一下。

代码

#include <cstdio>#define N 10000005using namespace std;bool f[N],g[N];int sum[N],p[N],tot;void work(){    f[1]=true;    for (int i=2;i<=10000000;i++)    {        if (!f[i])         {            p[++tot]=i;            for (int j=1;j<=tot;j++)            {                if (i*p[j]>10000000) break;                g[i*p[j]]=true;            }        }        for (int j=1;j<=tot;j++)        {            if (i*p[j]>10000000) break;            f[i*p[j]]=true;            if (i%p[j]==0) break;        }     }    for (int i=1;i<=10000000;i++)        if (g[i]||!f[i]) sum[i]=sum[i-1]+1;            else sum[i]=sum[i-1];}int main(){    //freopen("prime.in","r",stdin);    //freopen("prime.out","w",stdout);    int T;    scanf("%d",&T);    work();    while (T--)    {        int l,r;        scanf("%d%d",&l,&r);        printf("%d\n",sum[r]-sum[l-1]);    }    fclose(stdin);    fclose(stdout);}