补题报告————质数

错误题目:质数

质数

时间限制:1秒        内存限制:256M

题目描述

小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感。小 X 认为,质数是一切自然数起源的地方。

在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的数字。

但由于小 X 对质数的热爱超乎寻常, 所以小 X 同样喜欢那些虽然不是质数,但却是由两个质数相乘得来的数。

于是,我们定义,一个数是小 X 喜欢的数,当且仅当其是一个质数,或是两个质数的乘积。

而现在,小 X 想要知道,在 L 到 R 之间,有多少数是他喜欢的数呢?

输入描述

第一行输入一个正整数 Q,表示询问的组数。

接下来 Q 行。包含两个正整数 L 和 R。保证 L≤R,L,R <= 10^7 Q <= 10^5

输出描述

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

样例

输入

1

1 6

输出

5

思路:乍一看题,似乎很难,但是呢还是有思路的,我看见质数了之后,脑中有三个想法:

  1. prime判断:把区间中的数遍历一遍(两个数组,输入一个,判断一个),运用判断,标记一下(1代表留下)
  2. 埃氏筛:先打表,再把区间中的数遍历并判断一遍,然后输出,例如:

1

1  6

打表:

1

2

3

4

5

6

判断:

1

2

3

4

5

6

  补题报告————质数_第1张图片

输出:

2,3,5

  1. 欧拉筛:确保每个合数只被最小质因数筛掉,每个合数只会被筛到一次。

无语的是三种情况都想到了,可惜当时竟然只尝试了前两种……第三种方法没想到,

现在给大家看一下为什么前两种会pas掉:

  1. prime判断是需要遍历才能行的,但是我没有看到题目中的数据类型的范围……L,R <= 10^7 Q <= 10^5,这么大,这什么数据类型也装不下啊……
  2. 埃氏筛:我忽略了一个问题,埃氏筛是由非常严重的超时风险,埃氏筛的时间复杂度为 O(nlogn),故用该方法在处理 1e8 以上的数据时,会有时间超限的风险……

现在我们来看一下正解:

#include

using namespace std;

const N=1e7;

int l,r,q,cnt,prine[N];

bool st[N+5],num[N];

void ola(int m) {

for(int i=2; i<=m; i++) {

if(st[i]==0) {

num[i]=1;

prime[cnt++]=i;

}

for(int j=0;j

st[prime[j]*i]=1;

if(st[i]==0) {

num[prime[j]*i]=1;

}

if(i%prime[j]==0) {

break;

}

}

}

}

int main()

int q;

ola(N);

cin>>q;

for(int i=1;i

sum[i]=sum[i-1]+num[i];

}

while(q--){

cin>>l>>r;

cout<

}

return 0;

}

这道题主要知识点很复杂,最重要的有这几个:

  1. 1是标记需要输出的;
  2. 因为它说的是要求区间之内质数和两个质数的乘积,所以还要标记prime[j]*i(15行);
  3. 当我们看见输入中有:第一行输入一个正整数 Q,表示询问的组数。接下来 Q 行。包含两个正整数 L 和 R。保证 L≤R。L,R <= 10^7 Q <= 10^5类似的时,就能确定要用前缀和(27~29行)
  4. 注意输出格式!!!题目中说输出 Q 行,每行一个整数,别忘了cout<

你可能感兴趣的:(算法,c++,数据结构)