跳转至

Project Euler 10-Summation of primes(前缀和+二分)

Tags: Medium

Links: https://www.hackerrank.com/contests/projecteuler/challenges/euler010/problem


This problem is a programming version of Problem 10 from projecteuler.net

The sum of the primes below 10 is 2+3+5+7=17.

Find the sum of all the primes not greater than given N.

Input Format

The first line contains an integer T i.e. number of the test cases. The next T lines will contains an integer N.

Constraints

  • 1 \leq T \leq 10^4
  • 1 \leq N \leq 10^6

Output Format

Print the value corresponding to each test case in separate line.

Sample Input 0

2
5
10

Sample Output 0

10
17

#include <bits/stdc++.h>

using namespace std;

vector<int> seq;
int n = 0;
vector<long long> preSum;

bool isPrime(int n)
{
    int limit = sqrt(n) + 1;
    for (int i = 3; i <= limit; i += 2) {
        if (n % i == 0) return false;
    }

    return true;
}


void generate()
{
    seq.push_back(2), seq.push_back(3);
    n = 2;

    int i = 5;
    while (i <= 1e6 + 5) {
        if (isPrime(i)) { seq.push_back(i); ++n; }
        if (isPrime(i + 2)) { seq.push_back(i + 2); ++n; }
        i += 6;
    }

    preSum.resize(n + 1, 0);
    for (int i = 1; i <= n; ++i) preSum[i] = preSum[i - 1] + seq[i - 1];
}

long long solve(int target)
{
    int pos = upper_bound(seq.begin(), seq.end(), target) - seq.begin();
    return preSum[pos];    
}


int main()
{
    std::ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    generate();

    int caseNum; cin >> caseNum;
    int number;
    while (caseNum--) {
        cin >> number;
        cout << solve(number) << endl; 
    }

    return 0;
}

通过预处理预先生成10^6以内的素数,采用6倍数素数检验的方法来生成素数,然后对于每个样例采用二分的方法查找小于等于目标值对应的下标,然后直接返回前缀和。这样最坏的情况计算次数是10^4 \times \log{10^6},也完全不会超时。