POJ 2739 Sum of Consecutive Prime Numbers(素数表的应用)
原题地址
http://poj.org/problem?id=2739
题意:某些数字可以由连续几个素数的和表示,给定一个数字,求其有几种这样的表示方法。例:41=2+3+5+7+11+13 或 41=11+13+17
解题思路
素数表
既然要判断某个数能否表示为连续的素数和,那么首先就要知道如何求素数。
素数是数论和离散数学里非常重要的一部分,这里就如何用“筛法”得到n之内的素数表作总结(参考了以前做EOJ1006时存过的一个word文档)。
求[2,n]之间所有素数的素数筛法步骤如下:
- 申请大小为n+1大小的bool型数组visit[],用于遍历的同时确定素数,可以先全部初始化为true。
- 除2以外所有的偶数都不是素数,因此所有大于2的偶数的标为false,所有奇数的仍为true。
- 遍历所有奇数i。当i是素数时,i的所有倍数(大于等于2倍)必然是合数,将这些合数标为false,如果i已经不是素数,找i后一个素数做倍数筛法。
- 所有visit值为true的下标i即所求区间内的素数,存入目标表prime中。
这种筛法相比直接从i遍历到n筛去i的倍数,消耗时间可以大幅下降。
需要注意的几个点:
- 第2步的for循环的末尾循环体可以用 i+=2,第3步中的对i的成倍增加也可以用 j+=i
- 第3步中做遍历时,只需要对[2,sqrt(n)]间的数做筛法,因为若数字X存在1和其本身以外的因子,那么这对因子一定有一个数小于等于sqrt(n),容易反证得出结论。
枚举可能的连续素数和
这一步思想很简单,两层循环就够了:
先确定第一个素数,再从该素数的下一个素数开始依次累加,直到刚好累加到n则表达方法加一(或累加到大于n跳出),更换首个素数,重复这些步骤。
AC代码如下
#include <iostream>
#include <cstring>
#include <cmath>
#define MAXN 10005
using namespace std;
bool visit[MAXN];
int prime[MAXN] = {0};
int cnt = 0;
void BuildTable(int N) //素数筛法+打表
{
memset(visit, true, sizeof(visit));
for (int i = 4; i<=N; i += 2) //筛掉偶数,除2以外的偶数都不是素数
visit[i] = false;
for (int i = 3; i <= sqrt(N); i += 2) //检查所有奇数,如果x不是质数,那么它的某个因子一定不大于sqrt(x)
{
if (visit[i]) //i是素数(不存在比它小的因子)
{
int j = i<<1; //倍数至少是2,跳过i+1~2i
while(j < N) //筛掉从2i~N间i的倍数
{
if (j%i == 0) visit[j] = false;
j += i; //j成倍增加
}
}
}
for (int i = 2; i < N; ++i) //记录2~N间所有素数
if (visit[i]) prime[cnt++] = i;
}
int main()
{
BuildTable(10000);
int n;
while(cin >> n)
{
if (n == 0) break;
int ways = 0, Index1, Index2;
for (Index1 = 0; Index1 < cnt && prime[Index1] <= n; ++Index1) //连续素数和的第一个素数
{
int addup = prime[Index1];
for (Index2 = Index1+1; Index2 < cnt && addup <= n; ++Index2) //连续素数和的后续素数
{
if (addup < n)
addup += prime[Index2];
else if (addup == n) //累加到n,第一个素数后移
{
ways++;
break;
}
}
}
cout << ways << endl;
}
return 0;
}
内存占用:740K 耗时:0ms
算法复杂度:O(n^2)
相关题目
POJ 2262 Goldbach’s Conjecture
http://poj.org/problem?id=2262
POJ 2739 Sum of Consecutive Prime Numbers
http://poj.org/problem?id=2739
POJ 3006 Dirichlet’s Theorem on Arithmetic Progressions
http://poj.org/problem?id=3006