素数筛法(图解,C++)

题解:找出1-100中所有的素数(质数)

1、我们通常是遍历1-100,然后每个数字从2开始到根号i,只要取余等于0,则不是素数,否则就是素数来判断,像是这样:

bool judge(int x)			//判断x是否为素数
{
    
    
	for (int i = 2; i*i <= x; i++)	//遍历2至根号x
	{
    
    
		if (x % 2 == 0)			//若被整除,则返回假
			return false;
	}
	return true;				//退出循环 ,则返回真
}

在主函数中则是:

int main()	//写出1-1000中所有素数
{
    
    
	int n = 100;
	for (int i = 2; i <= n; i++)
	{
    
    
		if(judge(i)) cout << i << " ";	//是素数就打印
	}
	return 0;
}

但这样时间复杂度就达到了O(n²),数据超过1e5显然无法承受,这里介绍一种易理解的筛法优化时间:
一、埃式筛法
1、用一个数组储存所有的素数:

int ans[1001];		//储存素数

2、再用一个bool数组记录某个元素是否已经被筛去,初始全为false:

bool prime[1001] = {
    
     false };	

3、埃式筛法的思想为:从2-n遍历,每次找到记录为false的元素,就证明它则是素数(第一个是2,我们已知是素数了),第一次找到2后,筛掉所有2之后的倍数,数组记录为true,然后访问到数组值为false的元素3,因为3没有被刚才筛去,那么它一定也是素数,在筛去3之后的所有3的倍数……以此类推,具体图解如下:
在这里插入图片描述

4、每次找到素数后,则储存到素数数组中:

ans[index++] = i;				//数组记录素数,再让下标+1

具体完整实现代码如下:

#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
int index = 0;			//素数数组下标
bool prime[1001] = {
    
     false };	//记录是否被筛
int ans[1001];			//素数数组

int main()	//写出1-1000中所有素数
{
    
    
	int n = 100;
	prime[1] = 1;			//筛掉特殊的1
	for (int i = 2; i <= n; i++)
	{
    
    
		if (prime[i] == false)
		{
    
    
			ans[index++] = i;				//数组记录素数
			for (int j = i + i; j <= n; j += i)		//j+=i累加为i的倍数
			{
    
    
				prime[j] = true;			//标记为已删除
			}
		}
	}
	for (int i = 0; i < index; i++)
	{
    
    
		cout << ans[i] << " ";
	}

	return 0;
}

后语:33d,看了好几个筛法,就感觉这个容易理解,欧拉筛属实没看懂

猜你喜欢

转载自blog.csdn.net/Kyrie_irving_kun/article/details/114876471
今日推荐