1. 程式人生 > >演算法之素數篩法

演算法之素數篩法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

<1>方法一


//判斷是否是一個素數int IsPrime(int a)//0,1,負數都是非素數 if(a <= 1){  return
0; } //計算列舉上界,為防止double值帶來的精度損失,所以採用根號值取整後再加1,即寧願多列舉一個,也不願少列舉一個數 int bound = (int)sqrt(a) + 1for(int i = 2;i < bound;i++){  //依次列舉這些數能否整除x,若能則必不是素數  if(a % i == 0){   return 0;  } } return 1;}


<2>方法二


#define
MAXSIZE 10001
int Mark[MAXSIZE];int prime[MAXSIZE];//判斷是否是一個素數  Mark 標記陣列 index 素數個數int Prime()int index = 0memset(Mark,0,sizeof(Mark)); for(int i = 0;i < MAXSIZE;i++){  //已被標記  if(Mark[i] == 1){   continue;  }  else{   //否則得到一個素數
   prime[index++] = i;   //標記該素數的倍數為非素數   for(int j = i*i;j < MAXSIZE;j += i){    Mark[j] = 1;   }  } } return index;}

<3>方法三

這種方法比較好理解,初始時,假設全部都是素數,當找到一個素數時,顯然這個素數乘上另外一個數之後都是合數

把這些合數都篩掉,即演算法名字的由來。但仔細分析能發現,這種方法會造成重複篩除合數,影響效率。

比如10,在i=2的時候,k=2*15篩了一次;在i=5,k=5*6 的時候又篩了一次。所以,也就有了快速線性篩法。

int Mark[MAXSIZE];int prime[MAXSIZE];//判斷是否是一個素數  Mark 標記陣列 index 素數個數int Prime()int index = 0memset(Mark,0,sizeof(Mark));    for(int i = 2; i < MAXSIZE; i++)    {  //如果未標記則得到一個素數  if(Mark[i] == 0){   prime[index++] = i;  }  //標記目前得到的素數的i倍為非素數  for(int j = 0; j < index && prime[j] * i < MAXSIZE; j++)        {   Mark[i * prime[j]] = 1;   if(i % prime[j] == 0){                break;   }        }    } return index;}
利用了每個合數必有一個最小素因子。每個合數僅被它的最小素因子篩去正好一次。所以為線性時間。
程式碼中體現在:
if(i%prime[j]==0)break;
prime陣列 中的素數是遞增的,當 i 能整除 prime[j],那麼 i*prime[j+1] 這個合數肯定被 prime[j] 乘以某個數篩掉。
因為i中含有prime[j], prime[j] 比 prime[j+1] 小。接下去的素數同理。所以不用篩下去了。
在滿足i%prme[j]==0這個條件之前以及第一次滿足改條件時,pr[j]必定是pr[j]*i的最小因子。

參考博文:點選開啟連結













習題練習點選開啟連結






           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述