7.13 线性筛素数

Posted mudrobot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7.13 线性筛素数相关的知识,希望对你有一定的参考价值。

今天我们讲了一大堆数论的东西,目前本人稍微掌握一些的便是素数筛法,下面为了保护着珍贵的遗产,我决定写一篇博客来记录一下,

谈到素数筛法,相信大家岁熟悉的是暴力筛,我们大家只需要把数n的前1到sqrt(n)中所有的质数拿来和这个数n除一下看一下能否整除,如果能够整除,说明这个n是素数,然后就依次这样判定。

还有一种筛法是E筛,就是把每个数自己所有的倍数全部筛掉,当然其实你会发现我们只要把所有素数的倍数全部筛掉就可以了。

然后上面两种筛法都不是我们今天的重点,我们今天要讲的筛法是线性筛法——即通过某种方式使每个数都被自己的最小素因子筛去即可。注意:是最小的素因子!!!

算法实现

其实实现还是非常的简单了,我们从小到大依次枚举i,再枚举最小质因子pj,将i*pj筛去

而当i mod pj =0 时break出来,因为更大的pk,i*pk会被pj筛去而不是pk

举一个非常简单的例子,就是如果说现在我们正在检查数字6,我们正在用他筛去后面的一些合数,但是现在我们碰到了数字3,3是一个素数,并且6除3余0所以这时候我们应该把6break掉,因为在后面的后面早晚会碰见一个合数既被3整除又被6整除,就会被访问两次,为了降低复杂度先break掉就只是他访问了一次,节约了时间。

下面上一个代码:

大家看一看应该也就懂了:

#include<bits/stdc++.h>
using namespace std;
bool mark[1000005];
int p[1000005];
int main()
{
	memset(mark,false,sizeof(mark));
	int n;
	int cnt=0;
	scanf("%d",&n);
	for(int i=2;i<=n;++i)//枚举筛第i个数 
	{
		if(!mark[i]) p[++cnt]=i;
		for(int j=1;j<=cnt&&i*p[j]<=n;++j)
		{
			mark[i*p[j]]=true;
			if(i%p[j]==0) break;//important
		}
	}
	for(int i=1;i<=cnt;++i)
	{
		printf("%d ",p[i]);
	} 
	return 0;
}

以上是关于7.13 线性筛素数的主要内容,如果未能解决你的问题,请参考以下文章

浅谈线性素数筛

线性筛素数(欧拉筛)

线性筛素数(欧拉筛)

线性筛素数(欧拉筛)

单纯的线性筛素数

线性筛素数(欧拉筛)