普通筛法:
暴力寻找..
for(int i = 2;i <= n;i ++)
{
bool flag = 0;
for(int j = 2;j < i;j ++)
{
if(i%j == 0)
flag = 1;
}
if(flag == 0)
prime[++cnt] = i;
}
埃式筛法:
for(int i = 1;i <= sqrt(n);i ++)
{
if(!vis[i])
for(int j = i*i;j <= n;j += i)
{
vis[j] = 1;
}
}
线性筛:
线性筛法:
理解if(i%prime[ j ]==0)是关键。
原理:
1. 任何一个合数都可以表示成一个质数和一个数的乘积
2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
A = x * y; (假设y是质数,x合数)
x = a * b; (假设a是质数,且a < x——>>a<y)
-> A = a * b * y = a * Z (Z = b * y)
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积!!!!
这也是理解代码中 if(i%primes[j] == 0)break;的关键
例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查primes[1]=2即可,因为对于大于primes[1]的质数,像3,有:
8*3 = 2*4*3 = 12*2
也就是说24(8*3=24)并不需要在8时检查,在12时才检查
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool np[2333333];//不是素数
int prime[2333333];//是素数
int cnt = 0;
int main()
{
int n;
cin>>n;
np[1] = 1;
for(int i = 1;i <= n;i ++)
{
if(!np[i])
prime[++cnt] = i;
for(int j = 1;j <= cnt;j ++)
{
if(prime[j]*i > n) break;
np[prime[j]*i] = 1;
if(i%prime[j] == 0) break;
}
}
for(int i = 1;i <= cnt;i ++)
{
cout<<prime[i]<<endl;
}
return 0;
}