題目要求:給定 M ≤ N ≤ 10^4,輸出第 M 到第 N 個素數(即 P_M, P_{M+1}, ..., P_N),每行 10 個,空格分隔,行尾無多餘空格。本文對比試除法與埃拉托斯特尼篩法兩種實現,分析複雜度、邊界條件、輸出格式控制技巧,給出生產級代碼模板。
#include#include #include bool is_prime(int n) { if (n < 2) return false; int limit = (int)sqrt(n); for (int i = 2; i <= limit; i++) { if (n % i == 0) return false; } return true; } int main() { int M, N; scanf("%d %d", &M, &N); int count = 0; // 已找到的素數個數 int printed = 0; // 當前行已打印個數 for (int i = 2; count < N; i++) { if (is_prime(i)) { count++; if (count >= M) { printf("%d", i); printed++; if (printed % 10 == 0 || count == N) { printf("\n"); } else { printf(" "); } } } } return 0; }
需預估第 N 個素數的上界。由素數定理 P_n ≈ n ln n,N=10000 時 P_N ≈ 10000 * 9.21 ≈ 92100,取上界 110000 保證覆蓋。
#include#include #include #define MAX_SIEVE 110000 // 足夠覆蓋第 10000 個素數 int main() { int M, N; scanf("%d %d", &M, &N); // 1. 篩法生成所有素數 bool is_composite[MAX_SIEVE + 1] = {false}; int primes[MAX_SIEVE / 10]; // 足夠大 int prime_cnt = 0; for (int i = 2; i <= MAX_SIEVE; i++) { if (!is_composite[i]) { primes[prime_cnt++] = i; if ((long long)i * i <= MAX_SIEVE) { for (int j = i * i; j <= MAX_SIEVE; j += i) { is_composite[j] = true; } } } } // 2. 輸出第 M 到第 N 個 (數組索引 0-based) int printed = 0; for (int i = M - 1; i < N; i++) { printf("%d", primes[i]); printed++; if (printed % 10 == 0 || i == N - 1) { printf("\n"); } else { printf(" "); } } return 0; }
| 維度 | 試除法 | 篩法 |
|---|---|---|
| 時間複雜度 | O(N √P_N) ≈ O(N^1.5) | O(UpperBound log log UpperBound) |
| 空間複雜度 | O(1) | O(UpperBound) |
| N=10000 實測耗時 | ~10-50ms | ~1-5ms (含篩選) |
| 代碼複雜度 | 極低 | 中等 |
| 適用場景 | 單次查詢、N較小、內存受限 | 多次查詢、N較大、追求極致速度 |
// 統一模式:printed 計數器
int printed = 0;
for (...) {
printf("%d", prime);
printed++;
if (printed % 10 == 0 || is_last) {
printf("\n");
} else {
printf(" ");
}
}
// 關鍵:行尾無空格,靠 printed%10==0 判斷換行,is_last 判斷最後一個
輸入 輸出前 3 行 說明 5 2711 13 17 19 23 29 31 37 41 43\n47 53 59 61 67 71 73 79 83 89\n97 101 103樣例:第5~27個素數 1 102 3 5 7 11 13 17 19 23 29前10個 100 100541單個輸出 9991 10000104659 104677 104681 104683 104693 104701 104707 104711 104717 104723末尾邊界 七、 總結:選型決策
- PAT 甲級/乙級單次提交:試除法代碼最短、調試最快、完全足夠 (N≤10000),首選。
- 多測試用例/大 N/嵌入式高性能:預計算篩法/線性篩,一次篩選多次查詢。
- 輸出格式:統一用
printed計數器控制「10個換行、非10倍數加空格、最後換行」,避免行尾多餘空格導致格式錯誤。- 素數上界估算:
n (ln n + ln ln n)(Rosser 定理) 給出嚴格上界,工程中乘 1.2~1.5 安全系數。核心收穫:求素數是「算法工具箱」入門題。掌握試除法 sqrt 優化、埃氏篩 i*i 起步、線性篩最小質因子標記三層進階,並能根據數據規模、查詢模式、內存限制做工程選型,是從「會寫代碼」到「工程化解決問題」的關鍵標誌。格式控制看似瑣碎,實則是「細節決定成敗」的典型體現。