You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何改造n位素数生成代码以支持指定前m位搜索?

改造埃氏筛实现指定前缀的大素数搜索

要实现指定前m位搜索素数,核心是先把搜索范围缩小到以目标前缀开头的n位数区间,再用适合大区间的分段埃氏筛(Segmented Sieve)来筛选——普通埃氏筛在处理10位数这类大区间时,内存会不够用,分段筛能解决这个问题。

步骤说明

  1. 确定搜索区间
    假设要找n位数中前m位为prefix的素数:

    • 起始值:start = prefix * pow(10, n - m)(比如n=10,m=3,prefix=111,start=111*1e7=1110000000)
    • 结束值:end = (prefix + 1) * pow(10, n - m) - 1(上面的例子就是1119999999)
      注意:要确保prefix的位数是m,比如m=3时prefix不能是12(两位数)。
  2. 用分段埃氏筛筛选区间内的素数
    分段筛的逻辑是:

    • 先筛出所有小于等于sqrt(end)的素数(这些素数是用来标记大区间内合数的“工具”)
    • 用这些小素数,标记区间[start, end]里的所有合数
    • 剩下未被标记的就是区间内的素数

改造后的C++代码

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

// 生成小于等于limit的所有素数(普通埃氏筛)
std::vector<long long> generateSmallPrimes(long long limit) {
    std::vector<bool> isPrime(limit + 1, true);
    isPrime[0] = isPrime[1] = false;
    for (long long i = 2; i * i <= limit; ++i) {
        if (isPrime[i]) {
            for (long long j = i * i; j <= limit; j += i) {
                isPrime[j] = false;
            }
        }
    }
    std::vector<long long> primes;
    for (long long i = 2; i <= limit; ++i) {
        if (isPrime[i]) {
            primes.push_back(i);
        }
    }
    return primes;
}

// 在[start, end]区间内搜索素数,返回结果列表
std::vector<long long> findPrimesInRange(long long start, long long end) {
    // 处理边界情况:start小于2时调整为2
    if (start < 2) start = 2;
    if (start > end) return {};

    // 生成所有小于等于sqrt(end)的素数,用来标记区间内的合数
    long long sqrtEnd = sqrt(end);
    std::vector<long long> smallPrimes = generateSmallPrimes(sqrtEnd);

    // 初始化区间标记数组:isSegmentPrime[i]对应start+i是否为素数
    std::vector<bool> isSegmentPrime(end - start + 1, true);

    // 用每个小素数标记区间内的合数
    for (long long p : smallPrimes) {
        // 找到区间内第一个能被p整除的数
        long long firstMultiple = ((start + p - 1) / p) * p;
        // 如果第一个倍数是p本身(当start<=p时),从p*2开始标记
        if (firstMultiple == p) firstMultiple += p;
        // 标记所有p的倍数
        for (long long j = firstMultiple; j <= end; j += p) {
            isSegmentPrime[j - start] = false;
        }
    }

    // 收集区间内的素数
    std::vector<long long> primes;
    for (long long i = 0; i < isSegmentPrime.size(); ++i) {
        if (isSegmentPrime[i]) {
            primes.push_back(start + i);
        }
    }
    return primes;
}

// 主函数:指定前缀prefix、总位数n,搜索素数
int main() {
    // 示例:找10位数中前3位为111的素数
    int n = 10;          // 总位数
    int m = 3;           // 前缀位数
    long long prefix = 111; // 指定的前缀

    // 计算区间起始和结束值
    long long power = pow(10, n - m);
    long long start = prefix * power;
    long long end = (prefix + 1) * power - 1;

    std::cout << "搜索区间:" << start << " 到 " << end << std::endl;
    std::vector<long long> result = findPrimesInRange(start, end);

    std::cout << "找到的素数:" << std::endl;
    for (long long p : result) {
        std::cout << p << " ";
    }
    std::cout << std::endl;

    return 0;
}

代码关键说明

  • generateSmallPrimes:生成小素数,用来标记大区间的合数,避免直接处理超大数组的内存问题。
  • findPrimesInRange:核心的分段筛实现,只维护区间大小的标记数组,内存占用极低(比如10位数的区间是1e7个数,对应约10MB的bool数组,完全没问题)。
  • 主函数里的区间计算:直接通过前缀和位数算出搜索范围,把原本的全n位数搜索缩小到目标前缀的子区间,大幅降低计算量。

内容的提问来源于stack exchange,提问作者user19872448

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 20:10:48