#include <stdio.h>
#include <math.h>
int main() {
for (int i = 2; i <= 100; i++) {
int isPrime = 1;
for (int j = 2; j <= sqrt(i); j++) {
if (i % j == 0) { isPrime = 0; break; }
}
if (isPrime) printf("%d ", i);
}
return 0;
}
時間複雜度:O(n√n),適合教學與小範圍。
int primes[100], cnt = 0;
for (int i = 2; i <= 100; i++) {
int isPrime = 1;
for (int j = 0; j < cnt && primes[j] * primes[j] <= i; j++) {
if (i % primes[j] == 0) { isPrime = 0; break; }
}
if (isPrime) primes[cnt++] = i;
}
減少除法次數,利用已找到的質數作為除數。
#define MAX 100
int isComposite[MAX + 1] = {0};
for (int i = 2; i * i <= MAX; i++) {
if (!isComposite[i]) {
for (int j = i * i; j <= MAX; j += i)
isComposite[j] = 1;
}
}
for (int i = 2; i <= MAX; i++)
if (!isComposite[i]) printf("%d ", i);
時間複雜度 O(n log log n),空間 O(n),百萬級範圍首選。
int primes[MAX], cnt = 0;
int minFactor[MAX + 1] = {0};
for (int i = 2; i <= MAX; i++) {
if (minFactor[i] == 0) {
minFactor[i] = i;
primes[cnt++] = i;
}
for (int j = 0; j < cnt && primes[j] <= minFactor[i] && i * primes[j] <= MAX; j++)
minFactor[i * primes[j]] = primes[j];
}
每個合數僅被最小質因子篩一次,嚴格 O(n),適合需質因子分解的場景。
// 僅存儲奇數,位元組每位代表一個奇數
#define MAX 100
unsigned char sieve[(MAX >> 4) + 1] = {0};
#define IS_COMPOSITE(x) (sieve[(x)>>4] & (1 << (((x)>>1)&7)))
#define SET_COMPOSITE(x) (sieve[(x)>>4] |= (1 << (((x)>>1)&7)))
for (int i = 3; i * i <= MAX; i += 2)
if (!IS_COMPOSITE(i))
for (int j = i * i; j <= MAX; j += i << 1)
SET_COMPOSITE(j);
printf("2 ");
for (int i = 3; i <= MAX; i += 2)
if (!IS_COMPOSITE(i)) printf("%d ", i);
記憶體降低 8 倍,適合嵌入式環境或極大範圍(10^8+)。
| 演算法 | 耗時 (μs) | 記憶體 | 推薦場景 |
|---|---|---|---|
| 試除法 | ~15 | O(1) | 教學、極小範圍 |
| 優化試除 | ~8 | O(π(n)) | 輕量級工具 |
| 埃氏篩 | ~3 | O(n) | 通用首選 |
| 線性篩 | ~4 | O(n) | 需質因子分解 |
| 位元組篩 | ~5 | O(n/16) | 記憶體受限 |
i <= MAX 導致重複標記。i*i 而用 2*i,效率大幅下降。