Project Euler Problem 543 Prime-Sum Numbers

Prime-Sum Numbers

Problem 543

Define function P(n,k) = 1 if n can be written as the sum of k prime numbers (with repetitions allowed), and P(n,k) = 0 otherwise.

For example, P(10,2) = 1 because 10 can be written as either 3 + 7 or 5 + 5, but P(11,2) = 0 because no two primes can sum to 11.

Let S(n) be the sum of all P(i,k) over 1 ≤ i,kn.

For example, S(10) = 20, S(100) = 2402, and S(1000) = 248838.

Let F(k) be the kth Fibonacci number (with F(0) = 0 and F(1) = 1).

Find the sum of all S(F(k)) over 3 ≤ k ≤ 44


C++:

#include <iostream>
#include <cstring>
#include <cassert>

using namespace std;

//#define DEBUG

const int FIBMAXN = 44;

long fib[FIBMAXN+1];

void initfib(int n)
{
    fib[0] = 0L;
    fib[1] = 1L;
    for(int i=2; i<=n; i++)
        fib[i] = fib[i-2] + fib[i-1];
}

const int MAXN = 701408733;     // fib(44) = 701408733
const int PCOUNT = 36322186;
bool primeflag[MAXN];
long prime[PCOUNT];
int pcount;

void esieve(int n)
{
    memset(primeflag, true, sizeof(primeflag));

    pcount = 0;
    for(long i=2; i<n; i++) {
        if(primeflag[i]) {
            for(long j = i * i ; j<n; j+=i)
                primeflag[j] = false;
            prime[pcount++] = i;
        }
    }
}

long pcounting(long n) {
    long lower = 0L;
    long upper = pcount - 1;
    long middle;

    while (lower <= upper) {
        middle = lower + (upper - lower) / 2;
        if (prime[middle] < n)
            lower = middle + 1;
        else if (prime[middle] == n)
            return middle + 1;
        else
            upper = middle - 1;
    }

    return lower;
}

long long s(long n)
{
    long long sum = pcounting(n);

    if(n >= 4)
        sum += n / 2 -1;
    if(n >= 5)
        sum += pcounting(n - 2) - 1;
    if(n > 5) {
        long first_term = n - 6 + 1;
        long last_term = n - 2 * (n / 2) + 1;
        long term_count = (first_term - last_term) / 2 + 1;
        sum += (first_term + last_term) * term_count / 2;
    }

    return sum;
}

void solve()
{
    long long sum = 0;
    for(int i=3; i<=FIBMAXN; i++)
        sum += s(fib[i]);

    cout << "Sum[S(F(k))](k=3..44) = " << sum << endl;
}

void benchmark()
{
    assert(s(10) == 20);
    assert(s(100) == 2402);
    assert(s(1000) == 248838);
}

int main()
{
    initfib(FIBMAXN);

#ifdef DEBUG
    for(int i=0; i<=FIBMAXN; i++)
        cout << i << ": " << fib[i] << endl;
#endif

    esieve(MAXN);

#ifdef DEBUG
    cout << pcount << endl;

    benchmark();
#endif

    solve();

    return 0;
}



posted on 2017-03-24 08:04  海岛Blog  阅读(145)  评论(0编辑  收藏  举报

导航