【C++/C】利用筛选法(埃筛法)解决素数个数(n以内素数个数)问题

利用筛选法(埃筛法)解决素数个数问题

例题: n以内素数个数

输入格式:

请给出最大整数以内的一个数字n。

输出格式:

输出n以内素数的个数。

输入样例:

在这里给出一组输入。例如:

1000

输出样例:

在这里给出相应的输出。例如:

168

代码长度限制

16 KB

时间限制

10000 ms

内存限制

128 MB

  当我们处理“N是否为素数”问题时我们通常会考虑使用循环求余来判断:

  1. 首先我们会定义i从2到sqrt(n)的循环
  2. 然后不断增加i,用if(N%i==0)来进行判断
#include<cstdio>
#include<cmath>
#include<algorithm>
#include <iostream>
#include <algorithm>
#include<iostream>
bool IsSu(int x)//判断素数
{
    int i;
    int k = (int)sqrt((double)x);
    for (i = 2; i <= k; i++)
    {
        if (x % i == 0)
        {
            return false;
        }
    }
    return true;
}
int main()
{
    int n;
    int count=0;
    scanf("%d", &n);
    for (int i = 2; i <= n; i++)
    {
        if (IsSu(i))//判断素数,是则加一
        {
            count++;
        }
    }
    printf("%d",count);
}

 但此种方法的n空间复杂度较大,遇到n足够大时就会产生超时

于是,可以考虑筛除法(埃筛法)

  1. 首先设置一个素数数组下标对应数字,其内容1或0代表此数为是或不是素数
  2. 先假设全是素数,再从i=2开始,如果为素数,则进入下层循环(将2的倍数改为非素数,一直到i=N结束),
  3. 上层循环则也需遍历一遍2到N
#include<cstdio>
#include<cmath>
#include<algorithm>
#include <iostream>
#include <algorithm>
#include<iostream>
using namespace std;
const int MAX = 1e9 + 10;//设置最大值
char su[MAX + 10];//用char类型节省内存,1则为是素数,0则不是。
int n;
int main()
{
	scanf("%d", &n);
	int count = 0;//记录素数个数

	for (int i = 2; i <= n; i++)//先将所有元素都认为是素数 
	{
		su[i] = 1;
	}
	
	for (int i = 2; i <= n; i++)//利用埃筛法制作素数数组
	{
		if (su[i] == 1)//如果是素数则进入循环,将他的倍数设为0
		{
			for (int j = i * 2; j <= n; j += i)//循环找到他的倍数
			{
				su[j] = 0;	//将其标记为非素数

			}
		}
	}

	for (int i = 2; i <= n; i++)//判断N以内的素数
		if (su[i])//如果是素数则个数加一
			count++;
	printf("%d", count);
	return 0;
}

关于的埃筛法内容推理:

    素数是仅能被它本身和1整除的任何整数。埃拉托斯特尼筛法,简称埃氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。算法思想:给出要筛数值的范围,找出其以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数3去筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去......

如图所示:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值