1. 程式人生 > >UVALive3399 UVA1210 POJ2739 Sum of Consecutive Prime Numbers【素數篩選+尺取法】

UVALive3399 UVA1210 POJ2739 Sum of Consecutive Prime Numbers【素數篩選+尺取法】

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 25286 Accepted: 13793

Description

Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such representations does a given positive integer have? For example, the integer 53 has two representations 5 + 7 + 11 + 13 + 17 and 53. The integer 41 has three representations 2+3+5+7+11+13, 11+13+17, and 41. The integer 3 has only one representation, which is 3. The integer 20 has no such representations. Note that summands must be consecutive prime 
numbers, so neither 7 + 13 nor 3 + 5 + 5 + 7 is a valid representation for the integer 20. 
Your mission is to write a program that reports the number of representations for the given positive integer.

Input

The input is a sequence of positive integers each in a separate line. The integers are between 2 and 10 000, inclusive. The end of the input is indicated by a zero.

Output

The output should be composed of lines each corresponding to an input line except the last zero. An output line includes the number of representations for the input integer as the sum of one or more consecutive prime numbers. No other characters should be inserted in the output.

Sample Input

2
3
17
41
20
666
12
53
0

Sample Output

1
1
2
3
0
0
1
2

Source

題意簡述

  給定一個10000以內的n,判定n是否可以由幾個連續的素數(例如:2,3,5,7...)相加得到,輸出解的組數。

問題分析

  先用篩選法,篩選出素數備用,然後用尺取法解決。素數是單調遞增的,滿足用尺取法解決問題的條件。

  先求出最前面的子序列,使之素數和大於或等於n;

  重複後面一步,直到p素數大於n;

  若素數子序列和等於n,則解數計數;去掉子序列的第1個元素,子序列的後面再加上後續素數(只有素數值小於n時才累加),直到子序列和為0(後續素數已經大於n,無法加上,而不斷減去第1個元素)。

程式說明

  小於10000的最大素數為9973,如果只用小於等於9973的素數,結果會出問題。需要多算幾個素數,篩選出的素數有大於10000的素數就沒有問題了。程式中,素數篩選範圍是2到10000+10。

AC的C++語言程式如下:

/* UVALive3399 UVA1210 POJ2739 Sum of Consecutive Prime Numbers */

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>

using namespace std;

const int N = 10000;
int primes[N+1+10];

// Eratosthenes篩選法
void esieve(int n)
{
    memset(primes, 0, sizeof(primes));

    primes[0] = primes[1] = 1;
    for(int i=2; i<=sqrt(n); i++) {
        if(!primes[i]) {
            for(int j=i*i; j<=n; j+=i)  //篩選
                primes[j] = 1;
        }
    }

    for(int i=2, j=0; i<=n; i++)
        if(!primes[i])
            primes[j++] = i;
}

int main()
{
    esieve(N+10);

    int n;
    while(cin >> n && n) {
        int start, end, sum, ans;
        start = end = sum = ans = 0;
        for(;;) {
            while(primes[end] <= n && sum < n)
                sum += primes[end++];

            if (sum == n)
                ans++;

            sum -= primes[start++];

            if (sum <= 0)
                break;
        }
        printf("%d\n", ans);
    }

    return 0;
}