判决素数个数 (题目条件+运行时间限制)

题目描述:

 

输入两个整数X和Y,输出两者->>之间<<-的素数个数(包括X和Y)。

Input:

两个整数X和Y(1 <= X,Y <= 105)。

Output:

输出一个整数,表示X,Y之间的素数个数(包括X和Y)。

Sample Input:

1 100

Sample Output:

25

我的代码1:

#include <stdio.h>
int Isprime(int x){
    int i;
    for(i=2;i<x;i++){
        if(x%i==0) break;
    }
    if(i==x) return 1;
     return 0;
}

int main()
{
    int X,Y,i;
    int s=0;
    scanf("%d %d",&X,&Y);
    for(i=X;i<=Y;i++){
        if(Isprime(i)) s++;
    }
    printf("%d\n",s);
    return 0;
}

错误点1:题目只描述了A和B分别的范围,但是并没有说明A和B谁大谁小,所以我们得做个简单的交换。

错误点2:我写的代码用到了两个for循环,运行时间超过了题目限制。

于是我用到了倍数筛选法,先定义一个容量为100010的数组,多出10是为了防止鲁棒性(即程序在运行较复杂的问题出现的多占用内存问题,防止报错),从2开始遍历,到Y结束,将具有倍数关系的数字筛选出去,剩下的除了1就是素数了。

代码2:

#include <stdio.h>
int main()
{
    int Notprime[100010];
    int X,Y,t;
    int a=0;
    scanf("%d %d",&X,&Y);
    if(X>Y){
        t=X;
        X=Y;
        Y=t;
    }
    int i,j;
    for(i=2;i<=Y;i++){
        for(j=2*i;j<=Y;j+=i){
            Notprime[j]=1;
        }
    }
    for(i=X;i<=Y;i++){
        if(Notprime[i]==0&&i!=1) a++;
    }
    printf("%d\n",a);
    return 0;
}

运行结果:

但尽管如此,还是不满足题目条件,运行效率还是不够。

这里我们得接触到更高效率的素数筛法。

就代码2来看,当i=2的时候j能取到6,当i=3的时候,j同样重复取到了6,于是纵观数据100000,这其中得重复遍历多少次啊。所以我们得加以条件限制if(Notprime[j]==0)再进行遍历。说实话,这样写就已经符合题目限制了。

代码3:

#include <stdio.h>
int main()
{
    int Notprime[100010];
    int X,Y,t;
    int a=0;
    scanf("%d %d",&X,&Y);
    if(X>Y){
        t=X;
        X=Y;
        Y=t;
    }
    int i,j;
    for(i=2;i<=Y;i++){
        if(Notprime[i]==0){
        for(j=2*i;j<=Y;j+=i){
            Notprime[j]=1;
        }
        }
    }
    for(i=X;i<=Y;i++){
        if(Notprime[i]!=1&&i!=1) a++;
    }
    printf("%d\n",a);
    return 0;
}

但是遍历条件从j=2*i改成j=i*i,程序又得到了进一步的优化。带入一些数据不难发现,j=i*i将数据都覆盖了,而且重复率大大降低。

#include <stdio.h>
int main()
{
    int Notprime[100010];
    int X,Y,t;
    int a=0;
    scanf("%d %d",&X,&Y);
    if(X>Y){
        t=X;
        X=Y;
        Y=t;
    }
    int i,j;
    for(i=2;i<=Y;i++){
        if(Notprime[i]==0){
        for(j=i*i;j<=Y;j+=i){
            Notprime[j]=1;
        }
        }
    }
    for(i=X;i<=Y;i++){
        if(Notprime[i]!=1&&i!=1) a++;
    }
    printf("%d\n",a);
    return 0;
}

如果用函数写,可以这样

代码:

#include <stdio.h>
#include <math.h>
int prime(int x){
    int k;
    if(x==1) return 0;
    k=(int)sqrt(x);
    for(int i=2;i<=k;i++){
        if(x%i==0) return 0;
    }
    return 1;
}
int main()
{
    int n,m,i;
    scanf("%d %d",&m,&n);
    for(i=m;i<=n;i++){
        if(prime(i)==1) printf("%d ",i);
    }
    printf("\n");
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值