試除法判斷質數
試除法的思想
試除法是一種簡單且直觀的方法,用來判斷一個數是否為質數。它的基本思想是:對於待判斷的數 ( n ),從小到大地試除每個小於 ( n ) 的數 ( i ),如果 ( n ) 能被任何 ( i ) 整除且 () 和 (),則 ( n ) 不是質數;否則,( n ) 是質數。
下面是用試除法判斷一個數 ( n ) 是否為質數的示例程式碼:
#include <iostream>
using namespace std;
bool isPrime(int n) {
if (n <= 1) return false; // 小於等於1的數不是質數
if (n == 2) return true; // 2是質數
// 從2開始試除,一直試除到 sqrt(n)
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false; // 如果能整除,則不是質數
}
}
return true; // 如果沒有能整除的數,則是質數
}
int main() {
int n;
cout << "Enter a number: ";
cin >> n;
if (isPrime(n)) {
cout << n << " is a prime number." << endl;
} else {
cout << n << " is not a prime number." << endl;
}
return 0;
}
解釋:
-
函式
isPrime
:- 首先判斷如果 ( n \leq 1 ),則返回
false
,因為質數定義是大於1的正整數。 - 如果 ( n = 2 ),則返回
true
,因為2是質數。 - 接下來,用一個迴圈從2開始到 ( \sqrt{n} )(因為如果 ( n ) 有大於 ( \sqrt{n} ) 的因子,它的對稱因子必然小於 ( \sqrt{n} ))逐個試除。
- 如果能整除任何一個數 ( i ),則返回
false
,表示 ( n ) 不是質數。 - 如果迴圈結束都沒有找到能整除的數,則返回
true
,表示 ( n ) 是質數。
- 首先判斷如果 ( n \leq 1 ),則返回
-
主函式
main
:- 從使用者輸入一個數 ( n ),然後呼叫
isPrime
函式判斷它是否為質數,並輸出相應的結果。
- 從使用者輸入一個數 ( n ),然後呼叫
總結:
試除法是一種簡單但有效的方法來判斷一個數是否為質數。它的時間複雜度為 ( O(\sqrt{n}) ),效率較高,尤其適合用於判斷單個數是否為質數的場景。
2.埃氏篩法求質數
埃氏篩(Sieve of Eratosthenes)是一種用來找出一定範圍內所有素數的經典演算法。它由古希臘數學家埃拉託斯特尼斯(Eratosthenes)發明,用於解決尋找素數的問題。
演算法原理
埃氏篩的基本思想是:
- 初始化一個布林型別的陣列,稱為標記陣列(或篩選陣列),用來標記每個整數是否為素數。陣列的下標表示整數,陣列的值為
true
表示該下標對應的整數是素數,為false
表示不是素數。 - 從小到大依次遍歷每個整數
i
,若發現i
是素數,則將i
的所有倍數標記為非素數(即將對應位置的布林值設為false
),除了i
本身。
具體步驟如下:
- 初始化一個布林陣列
is_prime
,將陣列中所有元素初始化為true
。 - 將
is_prime[0]
和is_prime[1]
設為false
,因為 0 和 1 不是素數。 - 從
2
開始遍歷到sqrt(n)
,對於每個素數i
,將i
的所有倍數(除了i
本身)設為false
。 - 最終,所有值為
true
的下標即為素數。
演算法最佳化
- 減少遍歷範圍: 在埃氏篩中,我們只需要遍歷到
sqrt(n)
就可以了,因為如果i
是n
的因子,那麼n/i
也一定是n
的因子。 - 空間最佳化: 如果要找出的素數範圍不是很大,可以最佳化空間。例如,使用標記陣列只標記奇數,可以將空間使用減半。
示例
以找出小於等於 n
的所有素數為例,以下是使用埃氏篩的 C++ 實現示例:
#include <iostream>
#include <vector>
std::vector<int> sieve_of_eratosthenes(int n) {
std::vector<bool> is_prime(n + 1, true); // 預設所有數都是素數
std::vector<int> primes;
is_prime[0] = is_prime[1] = false; // 0和1不是素數
for (int i = 2; i * i <= n; ++i) {
if (is_prime[i]) {
for (int j = i * i; j <= n; j += i) {
is_prime[j] = false; // 將i的倍數標記為非素數
}
}
}
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) {
primes.push_back(i); // 收集所有素數
}
}
return primes;
}
int main() {
int n = 30; // 找出小於等於30的所有素數
std::vector<int> primes = sieve_of_eratosthenes(n);
std::cout << "Prime numbers less than or equal to " << n << " are:\n";
for (int prime : primes) {
std::cout << prime << " ";
}
std::cout << std::endl;
return 0;
}
在這個示例中,sieve_of_eratosthenes
函式返回小於等於 n
的所有素數的列表。程式首先初始化一個標記陣列 is_prime
,然後根據埃氏篩的演算法進行標記,最後收集所有值為 true
的下標作為素數輸出。
埃氏篩是一種高效的演算法,時間複雜度為 O(n log log n),適用於尋找較小範圍內的素數集合。