版权声明:本文章未经博主允许不得转载 https://blog.csdn.net/qq_42217376/article/details/88418482
欧拉筛法的原理就是每一个数只能被它最小的质因子删去,并且每个数只删除一次.
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int Max_n=100005;
typedef long long LL;
int prime[Max_n],is_prime[Max_n];
int n,num;
void get_prime(){
num=1;
rep(i,2,n) is_prime[i]=true;//首先先把每一个数标记成素数
//memset(is_prime[i],true,sizeof(is_prime));
rep(i,2,n){
if(is_prime[i]) prime[num++]=i;//如果这个数是素数,就放进素数表
rep(j,1,num-1){
if(i*prime[j]>n) break;//如果判断某一个数时,从某个素数开始>n了,那么乘后面的素数时,一定超出了范围.
is_prime[i*prime[j]]=false;//先把满足条件的标记成合数.
if(i%prime[j]==0) break;
}
}
}
int main(){
scanf("%d",&n);
get_prime();
rep(i,1,num-1) printf("%d%c",prime[i],i==num-1?'\n':' ');
return 0;
}
我们可以想象如果i%prime[j]==0成立,那么i一定是一个合数(有因子),那么我们一定可以把i分解成a*b,并且ab中 有一个数一定是素数.则有i*prime[j]=a*b*prime[j],我们假设a是i*prime[j]的最小素因子,
那么我们 遍历到b*prime[j]时一定能把i*prime[j]标记成合数,此时a是i*prime[j]的最小素数,所以在
遇到i的 时候我们直接跳出即可.
为什么if(i%prime[j]==0) break;在is_prime[i*prime[j]]=false;的后面呢?
此时是因为,我们遍历到的第一个素因子其实是2,这个素因子是最小的,
所以第一次的时候i*prime[j]一定 是被它最小的素因子筛去的.