0
点赞
收藏
分享

微信扫一扫

题目 1525: 找素数

kmoon_b426 2022-03-24 阅读 33

题目

给定区间[L, R] , 请计算区间中素数的个数。

输入
两个数L和R。

数据规模和约定
2 < = L < = R < = 2147483647 R-L < = 1000000

输出
一行,区间中素数的个数。

样例输入
2 11

样例输出
5

解题思路

本题用传统方法怎么都超时,看了题解才知道,需要用到埃氏筛法:这个方法用于寻找自然数n以内的所有素数,具体执行是剔除n以内所有的2到sqrt(n)之间的所有素数的倍数(不包含2、3、5等),剩下的即为素数。

易错点

  1. 注意变量是否需要long int,以防发生运行错误;
  2. 为了使hash散列的数组长度不超限,需要把[L,R]对应到[0,R-L];
  3. 题目要求从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;
}
举报

相关推荐

0 条评论