全素组
全素组
Problem Description
如果不大于指定整数n的3个素数之和仍为素数,则把这3个素数称为一个基于n的全素组。例如对于n=15, 素数3,5,11之和3+5+11=19为素数,则3,5,11称为一个基于15的全素组。
定义所有基于n的全素组中和最大的称为最大全素组。
输入整数n(n≤3000),输出基于n的全素组的个数和最大全素组的和。
定义所有基于n的全素组中和最大的称为最大全素组。
输入整数n(n≤3000),输出基于n的全素组的个数和最大全素组的和。
Input
每行一个整数
Output
每行2个整数,分别表示基于n的全素组的个数和最大全素组的和
Sample Input
15
Sample Output
5 31
解释:
对于这一个题目,基本上很好理解,就是找 a + b + c = d,且a,b,c,d都是素数,并且, a,b,c <= n, 因此可以推出,d < 3*n < 9000
这是一个比较重要的结论。一般想法就是,从2开始找到一个素数,然后开始找下一个素数,然后再在下一个素数,找到三个素数加起来,如果和也是素数,并且前三个素数都小于n, 那就得到一组解。这样写,没有错,但是对于时间来说,有点浪费时间。其中要判断每一个数是不是素数,这需要一个时间,并且可以发现,其实是一个重复的计算过程,难么我们就可以考虑,存起来。
如果说,要找到一个区间里面的素数,我觉得最好的办法就是打表的方式,它的时间基本上是O(n)级别的,所以,用不了多少时间。
1 /* 2 3 */ 4 #include<bits/stdc++.h> 5 6 using namespace std; 7 8 const int N = 3001; 9 10 int prime_flag[3*N]; 11 int prime_number[N]; 12 int prime_sum[N]; 13 int t = 0; 14 //素数打表,记录标记。prime_flag[i] = 1,表示数 i 是素数。 15 // prime_sum[t] 表示 第 t 个素数。 16 void init() 17 { 18 prime_flag[0] = prime_flag[1] = 1; 19 prime_sum[0] = prime_sum[1] = 0; 20 for (int i = 2; i < 3*N; i++) { 21 if (!prime_flag[i]) { 22 prime_number[t++] = i; 23 for (int j = 2; j * i < 3*N; j++) 24 prime_flag[j * i] = 1; 25 } 26 27 } 28 } 29 30 int main(){ 31 32 init(); 33 int n; 34 while (cin >> n) { 35 36 int sum_prime = 0; 37 int max_prime = 0; 38 for (int i = 0; prime_number[i] <= n && i < t; i++) { 39 for (int j = i+1; prime_number[j] <= n && j < t; j++) { 40 for (int z = j+1; prime_number[z] <= n && z < t; z++) { 41 int tx = prime_number[i] + prime_number[j] + prime_number[z]; 42 if (!prime_flag[tx]) { 43 44 sum_prime++; 45 max_prime = tx; 46 } 47 48 } 49 50 } 51 } 52 printf("%d %d\n", sum_prime, max_prime); 53 54 } 55 return 0; 56 }