首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

PAT 甲級 1020 求素數:篩法優化、區間輸出格式控制與 sqrt 試除法完整對比

     編輯:關於C語言

第 M 到第 N 個素數輸出:從試除法到埃拉托斯特尼篩的工程選型

第 M 到第 N 個素數輸出:從試除法到埃拉托斯特尼篩的工程選型

題目要求:給定 M ≤ N ≤ 10^4,輸出第 M 到第 N 個素數(即 P_M, P_{M+1}, ..., P_N),每行 10 個,空格分隔,行尾無多餘空格。本文對比試除法與埃拉托斯特尼篩法兩種實現,分析複雜度、邊界條件、輸出格式控制技巧,給出生產級代碼模板。

一、 試除法實現 (適合 N ≤ 10^4 輕量級場景)

#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 較大或多次查詢首選)

需預估第 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 判斷最後一個

五、 進階優化:線性篩 (O(n)) 獲取前 N 個素數

輸入輸出前 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末尾邊界


七、 總結:選型決策

  1. PAT 甲級/乙級單次提交:試除法代碼最短、調試最快、完全足夠 (N≤10000),首選。
  2. 多測試用例/大 N/嵌入式高性能:預計算篩法/線性篩,一次篩選多次查詢。
  3. 輸出格式:統一用 printed 計數器控制「10個換行、非10倍數加空格、最後換行」,避免行尾多餘空格導致格式錯誤。
  4. 素數上界估算:n (ln n + ln ln n) (Rosser 定理) 給出嚴格上界,工程中乘 1.2~1.5 安全系數。

核心收穫:求素數是「算法工具箱」入門題。掌握試除法 sqrt 優化、埃氏篩 i*i 起步、線性篩最小質因子標記三層進階,並能根據數據規模、查詢模式、內存限制做工程選型,是從「會寫代碼」到「工程化解決問題」的關鍵標誌。格式控制看似瑣碎,實則是「細節決定成敗」的典型體現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved