素数之筛法

筛法

筛素数的常用手段:

1、Eratosthenes 筛法

复杂度:O(n log (log n))

从小到大找到一个素数,筛掉所有它的倍数。

代码:

 1 void Prim(int n)
 2 {
 3     //Eratosthenes筛选法
 4     memset(check,false,sizeof(check));
 5     int tot = 0;
 6     for(int i = 2;i  <= n;i ++)
 7         if(!check[i])
 8         {
 9             prim[tot++] = i;
10             for(int j = 2*i;j <= n;j += i)
11                 check[j] = true;
12         }
13 }
View Code

 

 

2、Euler 筛法(重要!!!)

复杂度:O(n)

鉴于前者算法的优化,因为上面的算法一个非素数可能会被多个质因数筛多次,浪费了,所以优化掉这个,只用一个数最小的质因数排除(筛掉)这个数字。

 

 1 void Euler_prim(int n)
 2 {
 3     //欧拉筛选法     避免上面筛选法中的重复筛选
 4     memset(check,false,sizeof(check));
 5     int tot = 0;
 6     for(int i = 2;i <= n;i ++)
 7     {
 8         if(!check[i]) prim[tot ++] = i;
 9         for(int j = 0;j < tot;j ++)    //遍历已经找到的素数
10         {
11             if(i * prim[j] > n) break;   //后面相乘已经超出 n 的范围,没有查找的必要了
12             check[i * prim[j]] = true;    //表示这个数字不是素数
13             if(i % prim[j] == 0) break;   
14         }
15     }
16 }

 

 

重点解释下 if (i%prim[j]==0) break 这句话:

因为prim[j]是i的最小质因数了,如果这时候继续筛下去,下一个数为i*prim[j+1],因为 i=prim[j]*k,对于这个数来说最小质因数是prim[j],而这时却要用prim[j+1]来筛,则与我们要达到的要求、效果违背,这个数肯定会在以后被Prim[j]筛掉,所以直接break就行了,后面的肯定也会被prim[j]筛掉。

(不知道这样理解对不对。。。)

 

 

 

 

 

fighting fighting fighting !!!

posted on 2018-11-08 13:06  Frank-King  阅读(205)  评论(0编辑  收藏  举报