题目描述:
已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。
输入输出格式
输入格式:
键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)
输出格式:
屏幕输出,格式为:
一个整数(满足条件的种数)。
输入输出样例
输入样例#1:
4 3
3 7 12 19
输出样例#1:
1
思路:
找到这些组合,显然是一个搜索问题。如果直接用DFS方法进行搜索,会导致出现组合重复排列的情况。所以每一次的搜索初始位置都比上一次加一。代码如下:
#include<iostream>
#include<cmath>
const int MAX = 30;
using namespace std;
int n, k;//数的总数和选取的数的总数
int _count = 0;//the total number of prime numbers
int sum = 0;//记录搜索时相加的和
int a[MAX];///记录数据
//a function of prime numbers
bool isPrime(int x) {
if (x <= 1)
return false;
else if (2 == x)
return true;
else {
for (int i = 2; i <= sqrt(x); i++)
if (0 == x % i)
return false;
}
return true;
}
//DFS搜索函数
/*这里我仔细讲解一下DFS,level表示的递归层数,在后面主函数调用时从零开始,starti表示搜搜索的初始位置。
我们先看递归窗口。若果starti>n-1且此时的层数还没有达到k,再往下搜索就越界了,所以我们return。但是如果在还没有越界的时候层数就达到k,那么我们就判断累加和sum是否为素数。是的话计数器加一。然后在return。
最后我们看一看主体部分。搜索,就要把每种组合都找出来。我们用循环,从starti到n,不断变换初始搜索位置。当starti是搜索的初始位置时,sum加上a[starti],然后继续递归搜索,递归层数加一,但要注意,为了防止重复,我们把初始搜索位置也加一,这样不需要用vis数组记录是否访问。
最后,要释放sum,也就是减去a[j]即可
*/
void DFS(int a[MAX], int level, int starti) {
if (starti > n - 1 && level < k)
return;
if (level == k) {
if (isPrime(sum))
_count++;
return;
}
for (int j = starti; j < n; j++) {
sum += a[j];
DFS(a, level + 1, j + 1);
sum -= a[j];
}
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++)
cin >> a[i];
DFS(a, 0, 0);
cout << _count;
return 0;
}