除 2 和 3 以外,所有素數都分布在 6 的倍數兩側,即形式為 6k-1 或 6k+1(k ≥ 1)。這是因為:
結合孿生素數定理:若 N-1 和 N+1 都是素數(孿生素數),則 N 必是 6 的倍數。
6k-1 和 6k+1 的數#include <cstdio>
#include <cmath>
#include <cstring>
char* GetPrimesLessN(int nSize) {
char* flag = new char[nSize];
memset(flag, 1, nSize); // 1 表示可能是素數
flag[0] = flag[1] = 0; // 0,1 非素數
// 標記 2 的倍數
for (int i = 4; i < nSize; i += 2) flag[i] = 0;
// 標記 3 的倍數
for (int i = 6; i < nSize; i += 3) flag[i] = 0;
int limit = (int)sqrt(nSize) + 1;
for (int i = 5; i <= limit; i += 6) { // 6k-1
if (flag[i]) {
for (int j = i * i; j < nSize; j += 2 * i) flag[j] = 0;
}
int ip1 = i + 2; // 6k+1
if (ip1 <= limit && flag[ip1]) {
for (int j = ip1 * ip1; j < nSize; j += 2 * ip1) flag[j] = 0;
}
}
return flag; // 調用者負責 delete[]
}
int main() {
const int LIMIT = 1000000;
char* primes = GetPrimesLessN(LIMIT);
int count = 0;
for (int i = 2; i < LIMIT; ++i) if (primes[i]) ++count;
printf("Primes < %d: %d\n", LIMIT, count);
delete[] primes;
return 0;
}
| 算法 | N=10^7 耗時 | 內存佔用 |
|---|---|---|
| 普通埃氏篩 | ~1.2s | 10 MB |
| 6k±1 優化篩 | ~0.4s | 10 MB |
| 位壓縮優化篩 | ~0.25s | 1.25 MB |