素数筛选法

题目要求:统计出从1到n中的素数个数

1.最原始的做法
依次遍历每个数,每拿到一个数,对它进行判断,如果是素数,则标记并统计。时间复杂度O(n * sqrt(n))。

2.简单筛选法

1)将所有prime[i]标记为1(prime[i]=1代表i是素数,先全部标记为1,后面逐步排除合数)

2)挑出第一个素数(prime[i]=1),并用该素数i排除在n范围内i的所有倍数

举例说明n=10的情况

i = 2, 则需要排除2的倍数4,6,8,10(这些必然不是素数)

i = 3, 则需要排除3的倍数6,9

i = 5,则需要排除5的倍数10

此处,有两个问题

①这样能保证排除所有的合数吗?

答案是肯定的。假设A是不超过n的合数,假设A=B*C(B<C),若B是素数,则说明通过B可排除A,若B是合数,则B一定可以继续分解,如B=D*E(D<E),直到第一个数为素数为止。

②在简单筛选法的步骤2)中,i需要到多大,才能排除所有非素数?

答案是sqrt(n),采用反证法,如果A是小于n的合数,且A>sqrt(n),A=B*C(B和C一定有一个数小于sqrt(n)),根据理论①,如果B,C至少有一个合数,则一定可以继续拆,拆成第一个数是素数的形式,这样它一定会被那个素数排除掉。

先献上代码,后面还有一种优化后续再写

#include <iostream>
#include <cmath>
#include <memory.h>


#define MAX 10000


using namespace std;


int isPrime(int n)
{
    int cnt = 1;
   // cout<<2<<" ";
    for(int i = 3; i <= n; i++)
    {
        int temp = sqrt(i * 1.0);
        int j = 2;
        for(; j <= temp; j++)
        {
            if(i % j ==0)
                break;
        }
        if(j > temp)
        {
            cnt++;
          //  cout<<i<<" ";
        }


    }
    //cout<<endl;
    return cnt;
}


int simpleIsPrime(int prime[],int n)
{
    int cnt= 1; //非素数个数cnt标记为1(因为要从2开始筛选,1不是素数,所以将cnt置为1)
    memset(prime,sizeof(prime) * (n + 1),1);
    int temp = sqrt(n * 1.0);
    for(int i = 2; i <= temp; i++)
    {
        if(prime[i])
        {
// int temp = sqrt(i * 1.0);
            for(int j = 2 * i; j <= n; j = j + i)
            {
                if(prime[j])
                {
                    cnt++;
                    prime[j] = 0;
                }
            }
        }
    }
    return n - cnt;
}
int main()
{
    int n;
    cin>>n;
   // bool prime[];
    int prime[MAX];
    cout<<isPrime(n)<<endl;
    cout<<simpleIsPrime(prime,n)<<endl;
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值