質數識別 列舉演算法

2021-07-03 04:05:29 字數 2042 閱讀 8890

首先了解概念:質數,也被稱為素數,是指除了1跟它本身沒有其他因數的數。1既不是質數也不是合數,2是最小的質數。

問題:列舉小於任意數num的質數

可以把這樣乙個問題分解為兩個功能模組,list_prime(num)和is_prime(n),其中is_prime(n)巢狀在list_prime(num)中。

演算法1:首先從2開始迭代累加到num,該部分是list_prime(num)。對於任意乙個數n,需要判斷它是不是質數,即is_prime(n)。對2到n-1取餘(取模),如果發現有餘數為0的情況,則說明有因數存在,n不是質數。否則,n是質數。

我們發現,所有質數都是奇數,所以在從2迭代到num的過程中,每次累加2而不是1。

演算法2: list_prime(num)進行改進,從2迭代到num的過程中每次增加2,這樣每次只判斷奇數是不是質數,is_prime(n)與演算法1思路相同。可以提高50%的效率。

我們也發現,任何乙個合數都是由質因子組成的,比如10=2*5,12=2*2*3。所以在演算法2的基礎上,我們可以改進is_prime(n)。

演算法3:list_prime(num)與演算法2相同。對於is_prime(n),我們不需要考察從2到n-1的所有的數,只需要考察之前得到的質數即可。比如對於7,我們只需要看2,3,5是不是7的因子,而不需要看2,3,4,5,6。可以在演算法2的基礎上提高約50%的效率。

對於任何乙個數num,一定需要考察所有比num小的質數是不是其因子嗎?比如對於7,需要考察7能不能被2、3、5整除麼?其實不需要,因為任何乙個合數都至少可以分解成兩個數,而其中乙個必然可以是質數。(任何乙個合數都可以轉化為若干質數相乘的形式)所以對於num,在所有小於它的質數中,我們只需要判斷「前一半」(嚴格說是前一部分)是不是num的因子即可,因為另外的「後一半」要依靠前一半存在。

比如對於11,我們判斷2、3都不是其因子,5和5以後就不需要了,因為若因子有5,一定存在另乙個大於5的因子y使得5*y=11,但11比25都小,所以更不可能有5*y=11了。所以我們可以用質數的平方來作判斷條件,如果比當前質因子平方大或相等就繼續判斷,如果小則返回true。比如對於num=11

2*23*35*5>num, 返回true,num是質數。因為不可能有5和5以後的質數作為num的因子了,若有則必有小於5的質數作為num的另乙個因子,但之前判斷它們都不是。

演算法4:list_prime(num)與演算法3相同。對於is_prime(n),我們不需要考察之前得到的所有質數即可,只考察平方小於等於n的質數是不是其因子。

ruby的**如下

$arr=

$arr[0]=2

defadd_prime(n)

3.step(n,2)

end

defis_prime?(number)

j=0

while$arr[j]*$arr[j]<=number

returnfalseifnumber%$arr[j]==0

j+=1

end

returntrue

end

add_prime(50)

print $arr.join(","),"\n"

找質數 列舉

一天蒜頭君猜想,是不是所有的偶數 除了 2 都可以用兩個質數相加得到呢?於是聰明的蒜頭君就找你來驗證了。輸入格式 第一行輸入乙個整數 t 表示測試組數。接下來 t 行,每行乙個整數 n。輸入格式 348 20輸出格式 輸出兩個整數,因為答案可能有多個,所有要求輸出的這兩個整數是所有答 案中字典序最小...

質數的和與積 列舉

兩個質數的和是 s,它們的積最大是多少?輸入格式 乙個不大於 10000 的正整數s,為兩個質數的和。輸出格式 乙個整數,為兩個質數的最大乘積。資料保證有解。輸出時每行末尾的多餘空格,不影響答案正確性 樣例輸入 50樣例輸出 589解題思路1 通過了19個知識點 還有最後乙個測試點 沒有過去 不知道...

演算法 質數,質因數,篩質數

質數在大於1的整數中,如果只包含1和本身這兩個約數,就被稱為質數,或者叫素數。有3中形式 由於sqrt 計算較慢。不推薦 bool is prime int n 由於i i有可能會大於n,而當n較大時,可能會爆int,從而成為負值。不推薦 bool is prime int n 推薦 試除法 boo...