筛法
筛选法又称筛法,具体做法是:先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数
第一种:Eraosthenes(埃拉托斯尼筛法)埃氏筛法
时间复杂度O(nlogn)
利用当前已经找到的素数,从后面的数中筛去当前素数的倍数
#include<stdio.h>
#include<iostream>
#include<memory.h>
#define MAX 100
using namespace std;
int prime[MAX];
void Eratosthenes(){
for(int i = 0; i < MAX; ++i)
prime[i] = 1;
prime[0] = prime[1] = 0;
for(int i = 2; i < MAX; ++i){
if(!prime[i])
continue;
for(int j = i * 2; j < MAX;j += i)
prime[j] = 0;
}
}
int main(int argc, char const *argv[])
{
memset(prime, 0, sizeof(prime));
Eratosthenes();
for(int i = 1; i <= MAX; ++i){
if(prime[i] == 1)
printf("%d\n", i);
}
return 0;
}
第二种:欧拉筛法
时间复杂度O(n)
和埃氏筛法的区别是对于每一个要筛除的数,欧拉筛法只筛除一次
#include<stdio.h>
#include<iostream>
#define MAX 100
using namespace std;
int check[MAX];
int prime[MAX];
int tot = 0;
void euler(){
for(int i = 2; i <= MAX; ++i){
if(!check[i]){
prime[++tot] = i;
}
for(int j = 1; j <= tot && i * prime[j] <= MAX; ++j){
check[i * prime[j]] = 1;
//合数标为1,同时,prime[j]是合数i*prime[j]的最小素因子
if(i % prime[j] == 0)
break;
//即比一个合数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到
}
}
}
int main()
{
euler();
for(int i = 1; i <= tot; ++i)
printf("%d\n", prime[i]);
return 0;
}