筛选质数在C++中有多种方法,下面列出几种常见的方法并提供相应的代码示例:
1. 枚举法(试除法) 这是最简单的质数筛选方法,通过逐个检查每个数是否能被小于它的数整除来判断是否为质数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> #include <cmath> bool isPrime (int n) { if (n <= 1 ) return false ; for (int i = 2 ; i <= sqrt (n); i++) { if (n % i == 0 ) return false ; } return true ; } int main () { int n = 30 ; for (int i = 2 ; i <= n; i++) { if (isPrime (i)) { cout << i << " " ; } } return 0 ; }
2. 埃拉托斯特尼筛法(Sieve of Eratosthenes) 这种方法通过标记所有合数来筛选出质数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <vector> void SieveOfEratosthenes (int n) { vector<bool > prime (n + 1 , true ) ; for (int p = 2 ; p * p <= n; p++) { if (prime[p]) { for (int i = p * p; i <= n; i += p) { prime[i] = false ; } } } for (int p = 2 ; p <= n; p++) { if (prime[p]) { cout << p << " " ; } } } int main () { int n = 30 ; SieveOfEratosthenes (n); return 0 ; }
3. 线性筛法(Linear Sieve) 线性筛法避免了重复标记,通过每个数的最小质因子来筛选。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <vector> void LinearSieve (int n) { vector<int > primes; vector<bool > isPrime (n + 1 , true ) ; for (int i = 2 ; i <= n; ++i) { if (isPrime[i]) { primes.push_back (i); } for (int j = 0 ; j < primes.size () && i * primes[j] <= n; ++j) { isPrime[i * primes[j]] = false ; if (i % primes[j] == 0 ) break ; } } for (int prime : primes) { cout << prime << " " ; } } int main () { int n = 30 ; LinearSieve (n); return 0 ; }
4. 奇数筛法 优化后的埃拉托斯特尼筛法,只筛选奇数。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <vector> void OddSieve (int n) { if (n >= 2 ) cout << 2 << " " ; vector<bool > isPrime ((n + 1 ) / 2 , true ) ; for (int i = 3 ; i * i <= n; i += 2 ) { if (isPrime[i / 2 ]) { for (int j = i * i; j <= n; j += 2 * i) { isPrime[j / 2 ] = false ; } } } for (int i = 1 ; 2 * i + 1 <= n; ++i) { if (isPrime[i]) { cout << 2 * i + 1 << " " ; } } } int main () { int n = 30 ; OddSieve (n); return 0 ; }
5. 欧拉筛法(Euler Sieve) 欧拉筛法是对埃拉托斯特尼筛法的优化,保证每个合数只被筛选一次。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <vector> void EulerSieve (int n) { vector<int > primes; vector<bool > isPrime (n + 1 , true ) ; for (int i = 2 ; i <= n; ++i) { if (isPrime[i]) { primes.push_back (i); } for (int j = 0 ; j < primes.size () && i * primes[j] <= n; ++j) { isPrime[i * primes[j]] = false ; if (i % primes[j] == 0 ) break ; } } for (int prime : primes) { cout << prime << " " ; } } int main () { int n = 30 ; EulerSieve (n); return 0 ; }
这些方法各有优缺点,选择哪种方法取决于具体的应用场景和数据规模。