题目描述已知 n 个整数 x1, x2,…, x n,以及1个整数 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=334。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
输入输出格式输入格式:
键盘输入,格式为:
n,k(1≤n≤20,k<n)
x1,x2,…,xn(1≤xi≤5000000)
输出格式:
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入样例#1:
4 3 3 7 12 19
输出样例#1:
1
TIPS:(根据洛谷dalao本题因为n较小可以使用多重循环过而且不会TLE)本题最难的地方是不能重复计算。我们使用dfs深度优先搜索实现。dfs()有三个参数,i,sum,cnt。i表示当前加和的第一个数在整个输入中的位置,sum表示已加和的数的总和,cnt表示加和了多少个数。对于每个数都有加或者不加两种状况,针对两种情况分别搜索。这样就不会有重复情况出现。递归结束条件为数组搜完了或者cnt已经和k相等了。最后只要判断sum是不是素数就行了。
#include<cstdio>
#include<iostream>
#include<cmath>
#define SIZE 25
using namespace std;
void dfs(int i, int sum, int cnt);// i处理到第几个数, cnt已经加了几个数
int isprime(int n);
int in[SIZE];
int ans = 0;
int n, k;
int main(void){
cin >> n >> k;
for(int i = 0; i < n; i++){
cin >> in[i];
}
dfs(0,0,0);
dfs(0,in[0],1);
cout << ans << endl;
return 0;
}
int isprime(int n){
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0){
return 0;
}
}
return 1;
}
void dfs(int i, int sum, int cnt){
if(cnt == k && isprime(sum)){
ans++;
return ;
}
if(i < n - 1 && cnt < k )//没结束
{
dfs(i+1, sum, cnt);//不加下一个数字
dfs(i+1, sum + in[i+1],cnt+1);//加上下一个数字
}
return;
}