先上普通做法:O(n)
inline bool isPrime(int x){
if(x==1) return false;
if(x==2) return true;
for(int i=2;i<=x;i++){
if(x%i==0) return false;
}
return true;
}
然后O( n‾√ n )做法:
inline bool isPrime(int x){
if(x==1) return false;
if(x==2) return true;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0) return false;
}
return true;
}
然后埃拉托色尼筛法(普通筛法):
memset(check, 0, sizeof(check));
int tot = 0;
for (int i = 2; i <= n; ++i)
{
if (!check[i])
{
prime[tot++] = i;
}
for (int j = i+i; j <= n; j += i)
{
check[j] = 1;
}
}
然后是快速线性筛法:
half=SIZE/2;
int sn = (int) sqrt(SIZE);
for (i = 0; i < half; i++)
p[i] = true;// 初始化全部奇数为素数。p[0]对应3,即p[i]对应2*i+3
for (i = 0; i < sn; i++) {
if(p[i])//如果 i+i+3 是素数
{
for(k=i+i+3, j=k*i+k+i; j < half; j+=k)
// 筛法起点是 p[i]所对应素数的平方 k^2
// k^2在 p 中的位置是 k*i+k+i
// 下标 i k*i+k+i
//对应数值 k=i+i+3 k^2
p[j]=false;
}
}
//素数都存放在 p 数组中,p[i]=true代表 i+i+2 是素数。
//举例,3是素数,按3*3,3*5,3*7...的次序筛选,因为只保存奇数,所以不用删3*4,3*6....
需要证明的东西:博客:https://blog.csdn.net/dinosoft/article/details/5829550
一个数会不会被重复筛除。
合数肯定会被干掉。
根据上面红字的条件,现在分析一个数会不会被重复筛除。
设这个数为 x=p1*p2*…*pn, pi都是素数(1<=i<=n) , pi<=pj ( i<=j )
当 i = 2 时,就是上面①的情况,
当 i >2 时, 就是上面②的情况, 对于 i ,第一个能满足筛除 x 的数 y 必然为 y=p2*p3…*pn(p2可以与p1相等或不等),而且满足条件的 y 有且只有一个。所以不会重复删除。
证明合数肯定会被干掉? 用归纳法吧。
类比一个模型,比如说我们要找出 n 中2个不同的数的所有组合 { i , j } ,1<=i<=n, 1<=j<=n,
我们会这么写
for (i=1; i<n; ++i )
for (j=i+1; j<=n; ++j)
{
///......
}
我们取 j=i+1 便能保证组合不会重复。快速筛法大概也是这个道理,不过这里比较难理解,没那么直观。