连续质数之和题解

今天做了一道有意思的题,于是乎,我写下了题解。。。。。

  1. 预处理质数
  • 使用埃拉托色尼筛法找出所有小于等于 ( 4 \times 10^7 ) 的质数。
  • 将这些质数存储在一个数组中。
  1. 前缀和数组
  • 利用质数数组构建一个前缀和数组,其中每个元素表示从第一个质数开始累积到当前质数的和。
  • 这样可以快速求出任意区间内连续质数的和。
  1. 查询处理
  • 对每个输入的 ( n ),通过前缀和数组查找连续质数和等于 ( n ) 的情况。
  • 使用双重循环遍历前缀和数组,找出所有符合条件的区间。

下面是具体的代码实现:

#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 40000000;

// 标记质数的数组
bool is_prime[MAX_N + 1];
// 存储所有质数
vector<int> primes;
// 前缀和数组
vector<long long> prefix_sum;

void sieve() {
    fill(is_prime, is_prime + MAX_N + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i <= MAX_N; i++) {
        if (is_prime[i]) {
            primes.push_back(i);
            for (long long j = 1LL * i * i; j <= MAX_N; j += i) {
                is_prime[j] = false;
            }
        }
    }
}

void compute_prefix_sum() {
    long long sum = 0;
    for (int prime : primes) {
        sum += prime;
        prefix_sum.push_back(sum);
        if (sum > MAX_N) break;
    }
}

int count_ways(int n) {
    int ways = 0;
    for (int i = 0; i < prefix_sum.size(); i++) {
        for (int j = i; j < prefix_sum.size(); j++) {
            if (prefix_sum[j] - (i == 0 ? 0 : prefix_sum[i - 1]) == n) {
                ways++;
            } else if (prefix_sum[j] - (i == 0 ? 0 : prefix_sum[i - 1]) > n) {
                break;
            }
        }
    }
    return ways;
}

int main() {
    sieve();
    compute_prefix_sum();

    int T;
    cin >> T;
    vector<int> results;
    while (T--) {
        int n;
        cin >> n;
        results.push_back(count_ways(n));
    }

    for (int result : results) {
        cout << result << endl;
    }

    return 0;
}

解释

  1. 埃拉托色尼筛法
  • sieve 函数用来筛选所有小于等于 ( 4 \times 10^7 ) 的质数,并将它们存储在 primes 向量中。
  1. 前缀和计算
  • compute_prefix_sum 函数构建质数的前缀和数组 prefix_sum,每个元素表示从第一个质数到当前质数的累积和。
  1. 查询处理
  • count_ways 函数通过双重循环遍历 prefix_sum 数组,计算有多少种不同的表示形式使得连续质数的和等于给定的 ( n )。
  1. 主函数
  • 读取输入的 ( T ) 和每个 ( n ),并调用 count_ways 计算结果,最后输出结果。

这种方法通过预处理质数和前缀和数组,可以高效地处理每个查询。
image

@郑涞允1 题解请放到经验分享里谢谢
@桃桃J

so@我干嘛