java 素数欧拉筛选_[C++]欧拉素数筛的理解与实现

在传统的素数筛法中,我们使用了对于每一个数n,在 1~(√n) 范围内进行取模检查,这样逐一判断的复杂度为n(√n)。

但如果我们需要更快的筛法时怎么办?

于是著名的欧拉筛诞生了。它能将复杂度降为**O(n)**级别。

1.关键理解:

欧拉筛的原理是保证在 2~n 范围中的每一个合数都能被唯一分解成它的最小质因数与除自己外最大的因数相乘的形式。因此我们枚举2~n中的每一个数作为筛法中的“除自己外的最大因数”,如果它未被标记为合数,就先将它放入素数表内,再将这个最大因数与素数表中已经找到的素数作为最小质因数相乘,将得到的这些数标记为合数。最后输出得到的素数表即可。

但是我们如何保证每个合数都被唯一分解?

解决方法如下:

当此时取出的素数表中的素数(即枚举的最小质因子)整除于当前枚举的合数时,我们就停止循环素数表,开始枚举下一个合数。

证明如下:

设当前枚举的最小质因子prime[i]整除于合数n时,即我们要筛掉合数 n*prime[i] ;如果我们此时不退出,继续枚举下一个素数prime[i+1],对于将要筛掉的合数 n*prime[i+1] 由于插入顺序从小到大,则 prime[i+1]>prime[i]。由于prime[i]整除于合数n,所以必然合数 n*prime[i+1] 还可以被分解为

$$(\frac{n}{prime[i]}*prime[i+1])*prime[i]$$

显然,在上面的分解方式中,我们将要筛掉的合数分解为更小的质因子 prime[i] ,这不符合我们对于每一个数被唯一分解的要求,所以我们可在代码中加入一行判断整除关系的代码进行优化。

2.代码实现:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

inline void read(int &x){

x=0;int f=1;

char ch=getchar();

while(ch'9'){

if(ch=='-')

f=-1;

ch=getchar();

}

while(ch>='0'&&ch<='9'){

x=(x<<1)+(x<<3)+(ch^48);

ch=getchar();

}

x*=f;

}

bool IsPrime[100005];

int prime[50005];

int main(int argc, char const *argv[])

{

int n,top=1;

memset(IsPrime,1,sizeof(IsPrime));

read(n);

for(int i=2;i<=n;i++)

{

if(IsPrime[i])

prime[top]=i,top++;

for(int j=1;j

{

if(i*prime[j]>n)

break;

IsPrime[i*prime[j]]=0;

if(i%prime[j]==0)

break;

}

}

cout<

for(int i=1;i

cout<

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值