Primes Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1439 Accepted Submission(s): 610
Problem Description
Given a number n, please count how many tuple(p1, p2, p3) satisfied that p1<=p2<=p3, p1,p2,p3 are primes and p1 + p2 + p3 = n.
Input
Multiple test cases(less than 100), for each test case, the only line indicates the positive integer
n(n≤10000)
.
Output
For each test case, print the number of ways.
Sample Input
Sample Output
Source
BestCoder Round #18
首先素数肯定是要打出一个表的。。。。。
然后就可以有两个选择:
1:用两个循环,判断N减去两个素数的值是否为素数,如果是,方法加1——这里面有个坑,这三个素数是有顺序的而且可以相等,这时候就得动脑筋想一下
有两个素数相等的情况与三个数相等的情况对结果的影响了,结合代码解释:
#include <iostream>
#include <ctime>
using namespace std;
bool primelist[10005];//这个表用来判断是否为素数--真、不是素数,假、是素数
int prime[4000];//这个表用来存储1~1000000中的素数
int n,p1,p2,p3,i,j,k,flag,m;
int creatlist()//素数打表不解释。。。
{
int i,j;
primelist[0] = primelist[1] = true;
for(i = 4;i <10005;i+=2)
primelist[i] = true;
for(i = 3;i < 4000;i++)
if(!primelist[i])
for(j = i * i;j < 10005;j+=i)
primelist[j] = true;
j = 0;
for(i = 0;i <10000;i++)//提取素数存到prime中
if(!primelist[i])
prime[j++] = i;
return j;//返回素数的个数
}
int main()
{
k = creatlist();
while(cin >> n)
{
flag = 0;
for(i = 0;i < k;i++)//两重循环,如果p1 != p2 != p3,那么这一组数据会被计数六次(因为循环是从最小的素数开始的)在草稿纸上演算一次就知道啦
{
m = n - prime[i];
p1 = prime[i];
if(m <= 0) break;//当素数已经大于N时,后面的素数肯定不会满足了,跳出
for(j = 0;j < k;j++)
{
p2 = prime[j];
p3 = m - prime[j];
if(p3 <= 0) break;//同上
else if(!primelist[p3])//差值是素数,满足,开始计数
{
if((p1 == p2 && p1 != p3) || (p1 == p3 && p1 != p2) || (p2 == p3 && p1 != p2)) flag++;//当俩个数相等时(可以草稿纸演示),只会被记录三次,要使它变为6,所以每次要额外加一
else if(p1 == p2 && p2 == p3) flag+=5;//当三个数都相等时,只会被计数一次,所以额外加个5————因为结果会除6
flag++;//只要进入本循环,就要加一
//cout << p1 <<" " << p2 << " " << p3 << endl;//调试语句
}
}
}
cout << flag / 6 << endl;//每组数据都会重复计数6次,所以结果除6
}
return 0;
}//看不懂的童鞋多看几遍就好了。。。。
就是把结果打表————把所有素数求出来,把以三个素数相加的且小于1000000的值为下标的元素的值累加一,即a【N】的值代表组成N会有多少种方法。最后直接输出数组元素的值就好了,再贴一码。。。这个不是自己打的,讨论区来的。。。。解释是自己加的
#include<stdio.h>
#include<math.h>
#include<string.h>
int N,rel[11000],prim[11000],sushu[11000];
int main()
{
int i,j,k,t=0;
memset(prim,0,sizeof(prim));
memset(rel,0,sizeof(rel));
memset(sushu,0,sizeof(sushu));
for(i=2;i<10000;i++)//素数打表,不解释,这个方法比我的简单一点 = = 不过原理还是一样————直接赋值会比用取余运算判断素数要快
{
if(!prim[i])
{
sushu[t++]=i;
for(j=2;j<10000;j++)
{
if(i*j>=10000)break;
prim[i*j]=1;
}
}
}
for(i=0;i<t;i++)//三个循环遍历所有素数情况
for(j=i;j<t;j++)//从i开始避免出现重复的数据组成情况,所以最后的结果不需要像第一种情况除6
for(k=j;k<t;k++)//从j开始原因同上
{
if(sushu[i]+sushu[j]+sushu[k]>10000)break;//三个素数之和大于上限了,肯定不满足
rel[sushu[i]+sushu[j]+sushu[k]]++;//每组成一个数字,以该数据为下标的元素累加一,代表多出一种组成方法
}
while(scanf("%d",&N)!=EOF)
{
printf("%d\n",rel[N]);
}
return 0;
}