ALDS1_1_C:Prime Numbers[判断素数][埃拉托色尼筛法][快速线性筛法]

题目链接

先上普通做法: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 )做法:

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 便能保证组合不会重复。快速筛法大概也是这个道理,不过这里比较难理解,没那么直观。

猜你喜欢

转载自blog.csdn.net/qq_33982232/article/details/81677218