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 线性筛素数的主要内容,如果未能解决你的问题,请参考以下文章