素數的求解逐步改進

2021-09-01 07:44:01 字數 2889 閱讀 1882

1.位操作總結:

2.找素數演算法總結:

非常感謝上面兩篇部落格的仁兄,致謝!

尤其是讀了位操作的那篇文章,寫的非常好,希望各位都可以一次嘗試哈,沒準給你的程式增加乙個亮點

2的總結也很好,我只是在它的基礎上在詳細的給了些注釋,如果有不懂的地方就好理解了!

1.基礎補習

有乙個重要的性質:任何乙個合數一定可以表示成若干個素數之積。

如:4 = 2 * 2,6 = 2 * 3,12 = 2 * 2 * 3。也就是說,合數n一定是小於n的某個(或若干)素數的整數倍,反之,如果n不是任何比它小的素數的倍數,則n必然是素數。

這個性質就決定了下面的演算法基本思想

2.檢查是否是素數(這個是從基本概念出發的檢測演算法)

主要的改進就是檢測的範圍縮小從0---sqrt(n)

bool isprime(int n);//判斷是否為素數,初始都為素數

prime[0] = 0; //儲存素數的總個數

for(int n=2; n4.經典演算法改進版

其主要的改進的地方就是,檢測的思想,前面的檢測方法就是2到sqrt(a)依次除,看是否整除

改進的就不同了,它利用了合數的性質,利用已經找到的素數來除,這樣大大的減少了需要整除的次數,這個改進不錯!

/***它是上面經典演算法改進版

*這裡prime陣列中存的是素數,prime[0]中儲存素數總個數

*獲取0-n的所有素數

*/int* getprime1();//判斷是否為素數,初始都為素數

int i, n, flag;

prime[0] = 0; //儲存素數的總個數

for (n =2 ; n < len; n++)

//flag=1,則說明是素數,儲存

if (flag)

} cout<<"\ncount:"<5.厄拉多塞篩演算法

所謂厄拉多塞篩演算法就是:利用乙個空間換時間的思想,利用乙個輔助陣列來儲存素數的位置,然後利用的是篩選法,篩選出素數的倍數

那你就會發出乙個疑問?只是篩選出素數的倍數,那是不是還有遺漏啊?這個就看看1的性質吧,即所有合數,都可以分解成若干個素數。

*首先,將所有的陣列元素設為0,表示沒有已知的非素數。

*然後,將已知為非素數(即為已知素數的倍數)的索引對應的陣列元素設定為1。

*如果將所有較小素數的倍數都設定為1之後,a[i]仍然保持為0,則可判斷它是所找的素數。

/***厄拉多塞篩演算法:prime[0]中儲存素數總個數

*/int* getprime2(), pi=1;

int flag[len] = ;//判斷是否為素數,初始都為素數

//0,1不是素數

flag[0]=1;

flag[1]=1;

for(int i=2; i6,厄拉多塞篩演算法改進版

由於對於5來說,最大的缺憾就是利用了輔助陣列,那麼我們可以減少空間,反正都只是存0,1,為什麼不用位來儲存呢?這樣就大大的減少了空間的浪費了!

首先看看乙個為操作的事例:

/***用於位測試

* */

#include #include using namespace std;

int main(); //占用連續的20個位元組空間(每個int占用4位元組),每個位元組8位(1byte=8bit)

cout<> (i % 32)) & 1)

putchar('1');

else

putchar('0');

} putchar('\n');

return 0;

return 0;

}

在下面的演算法中就是利用了上面的操作,只要去看看我第乙個鏈結,裡面更詳細!

/**

*厄拉多塞篩演算法改進版:prime[0]中儲存素數總個數

*/int* getprime3(), pi=1; //實際素數的個數最多就是len / 3,故而沒用len

//用位替代int prime[len] = ;//判斷是否為素數,初始都為素數

int flag[len/32] = ;//每個int是4位元組=32bit(32位)可以儲存32個0,1,故而只需要len/32個長度的陣列即可

for(int i=2; i>(i%32))&1))else

*/ //-------------------------方法1(經典演算法62ms)----------------------------

//getprime();

/* int *a = getprime();

for(int i=1; i*/

//-------------------------方法1(經典演算法改進15ms)----------------------------

//getprime1();

/* int *a = getprime1();

for(int i=1; i*/

//----------------------------方法3(厄拉多塞篩演算法<1ms)----------------------------

//getprime2();

/* int *a = getprime2();

for(int i=1; i*/

//----------------------------方法3(厄拉多塞篩演算法改進<1ms)----------------------------

//getprime3();

int *a = getprime3();

for(int i=1; ifinish = clock();

cout<< "\ncost time: " << finish - start << " ms";

return 0;

}

改進的素數篩

最簡單的篩素數法方法就是從2開始,將所以2的倍數去掉,然後從3開始,將3的倍數去掉。根據這樣很容易寫出 下面 就是是篩素數法得到100以內的素數並儲存到primes陣列中。cpp view plain copy by morewindows const intmaxn 100 bool flag m...

關於素數的求解

質數 prime number 又稱素數,有無限個。乙個大於1的自然數,除了1和它本身外,不能被其他自然數整除,換句話說就是該數除了1和它本身以外不再有其他的 因數。求解整數n之前的所有素數及總數 include stdio.h include math.h int main if c sqrt i...

素數的求解方法

就判斷素數而言,事實上是非常簡單的了。根據定義,判斷乙個整數n是否是素數,只需要去判斷在整數區間 2,n 1 之內,是否具有某個數m,使得n m 0。可以這麼寫 int isprime int n return 1 事實上,這個演算法是o n 的,感覺是很快了,但是依舊無法滿足需求。所以有乙個演算法...