题目
给定区间[L, R] , 请计算区间中素数的个数。
输入
两个数L和R。
数据规模和约定
2 < = L < = R < = 2147483647 R-L < = 1000000
输出
一行,区间中素数的个数。
样例输入
2 11
样例输出
5
解题思路
本题用传统方法怎么都超时,看了题解才知道,需要用到埃氏筛法:这个方法用于寻找自然数n以内的所有素数,具体执行是剔除n以内所有的2到sqrt(n)之间的所有素数的倍数(不包含2、3、5等),剩下的即为素数。
易错点
- 注意变量是否需要long int,以防发生运行错误;
- 为了使hash散列的数组长度不超限,需要把[L,R]对应到[0,R-L];
- 题目要求从L到R的素数,因此,只需要将在L和R之间的2到sqrt®的倍数删去即可;否则,从2开始查找会时间超限。
代码
#include<stdio.h>
#include<math.h>
int hash[1000001];
int is_Prime(int a){
int i;
if (a<2)
return 0;
else if (a>2)
{
for (i=2;i<=sqrt(a);i++)//对于大于2的数
if (a%i==0)
return 0;
}
return 1;
}
long int max(long int a, long int b){
return (a>b) ? a:b;
}
int main()
{
long int i,j,temp;
long int L,R;//2<=L<=R<=2147483647
long int num=0;
scanf("%ld %ld",&L,&R);
for (i=2;i<=sqrt(R);i++)
{
if (is_Prime(i)==1)//是素数
{
for (j=max(L/i*i,2*i);j<=R;j+=i)
if (j>=L)
hash[j-L] = 1;
}
}
for (i=0;i<(R-L+1);i++)
if (hash[i]==0)
num++;
printf("%ld",num);
return 0;
}
错误代码
直接用传统的方法,时间超限(50分):
#include<stdio.h>
#include<math.h>
int is_Prime(int a){
int i;
if (a<2)
return 0;
else if (a>2)
{
for (i=2;i<=sqrt(a);i++)//对于大于2的数
if (a%i==0)
return 0;
}
return 1;
}
int main()
{
int i,L,R;//2<=L<=R<=2147483647
long int num=0;
scanf("%d %d",&L,&R);
if (L%2==0)
num+=is_Prime(L++);
for (i=L;i<=R;i+=2)//排除了所有偶数
num+=is_Prime(i);
printf("%ld",num);
return 0;
}
改成先把2、3、5、7倍数(不包含2、3、5、7)在hash散列当中标为1,在搜索其他的,还是时间超限(50分):(这种方法需要把 i ,j 设置为long int,因为当R是2147483647,在for循环最后一步+n的时候就会出现 i, j 超出int范围的情况,会提示运行错误)
#include<stdio.h>
#include<math.h>
int hash[1000001];
int is_Prime(int a){
int i;
if (a<2)
return 0;
else if (a>2)
{
for (i=11;i<=sqrt(a);i++)//对于大于2的数
if (a%i==0)
return 0;
}
return 1;
}
int main()
{
long int i,j;
int L,R,temp;//2<=L<=R<=2147483647
int m2=0,m3=0,m5=0,m7=0;
long int num=0;
scanf("%d %d",&L,&R);
for (i=L;i<=R;i++)
{
if (m2==0 && i%2==0 && i!=2)
{
m2 = i;
for (j=m2;j<=R;j+=2)
hash[j-L] = 1;
}
if (m3==0 && i%3==0 && i!=3)
{
m3 = i;
for (j=m3;j<=R;j+=3)
hash[j-L] = 1;
}
if (m5==0 && i%5==0 && i!=5)
{
m5 = i;
for (j=m5;j<=R;j+=5)
hash[j-L] = 1;
}
if (m7==0 && i%7==0 && i!=7)
{
m7 = i;
for (j=m7;j<=R;j+=7)
hash[j-L] = 1;
}
if (m2!=0 && m3!=0 && m5!=0 && m7!=0)
break;
}
for (i=0;i<(R-L+1);i++)
if (hash[i]==0 && is_Prime(i+L)==1)
num++;
printf("%ld",num);
return 0;
}