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

POJ 2635 The Embarrassed Cryptographer:篩素數 + 高精度模運算

     編輯:關於C++

題目大意

給大整數 K(< 10¹⁰⁰,字符串輸入)與上限 L(< 10⁶)。求 K 的最小素因子 p(p < L),輸出 BAD p;若無此類因子,輸出 GOOD。

解法:線性篩 + 字符串模運算

  1. 線性篩素數:O(L) 篩出所有 L 以內素數存入 primes[]。關鍵優化:每個合數僅被其最小素因子篩一次(for (j=0; j)。
  2. 高精度取模:對每個素數 p,按十進制位處理 K:rem = (rem * 10 + digit) % p。或原碼做法:每 3 位切分(基數 1000),rem = (rem * 1000 + chunk) % p,減少循環次數。
  3. 按素數從小到大遍歷,首個 rem == 0 即為答案。

線性篩核心代碼

for (int i = 2; i < L; ++i) {
    if (!vis[i]) primes[cnt++] = i;
    for (int j = 0; j < cnt && i * primes[j] < L; ++j) {
        vis[i * primes[j]] = 1;
        if (i % primes[j] == 0) break; // 保證每合數僅被最小素因子篩一次
    }
}

高精度模運算(基數 1000 版)

bool divisible(const char* K, int p) {
    int rem = 0, len = strlen(K);
    for (int i = 0; i < len; ) {
        int chunk = 0, d = 0;
        while (i < len && d < 3) chunk = chunk * 10 + (K[i++] - '0'), ++d;
        rem = (rem * 1000 + chunk) % p;
    }
    return rem == 0;
}

複雜度

  • 篩素數 O(L),L ≤ 10⁶ 约 7.8 萬個素數。
  • 每素數取模 O(|K|/3),最壞總 O(π(L) × |K|) ≈ 7.8×10⁴ × 33 ≈ 2.6×10⁶ 操作,極快。

總結

本題結合「線性篩素數」與「大整數模運算」。線性篩保證 O(L) 時間且每合數僅處理一次;大整數模運算利用模運算分配律逐位計算,基數 1000 優化常數。模板價值極高,適用於所有「大數找小因子」問題。

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