题目描述
Description
已知 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)。
输入描述
Input Description
键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)
输出描述
Output Description
屏幕输出,格式为:
一个整数(满足条件的种数)。
样例输入
Sample Input
4 3
3 7 12 19
样例输出 Sample Output
1
运行结果
测试点#xs1.in 结果: 内存使用量: 256kB 时间使用量: 1ms 测试点#xs2.in 结果: 内存使用量: 256kB 时间使用量: 0ms 测试点#xs3.in 结果: 内存使用量: 256kB 时间使用量: 0ms 测试点#xs4.in 结果: 内存使用量: 256kB 时间使用量: 1ms 测试点#xs5.in 结果: 内存使用量: 256kB 时间使用量: 20ms
思路:这题明显是回溯。先列举出所有排列的可能,但值得考虑的是 — “ 3+7+12” 和 “3+12+7” 是一样的。所以每次选第一个数后,这个数后面的就可以不选了,以免重复。
代码如下:
# include <iostream>
# include <cmath>
using namespace std;
int n, k, kase = 0;
bool vis[25];
long long sum = 0, s[25];
bool prime(long long s) {
for(long long i = 2; i <= sqrt(s); i++)
if(s % i == 0) return 0;
return 1;
}
void search(int x, int y) { //回溯过程就不说,y是一个新排列的数组下标。
for(int i = y; i <= n; i++) {
if(!vis[i]) {
sum += s[i]; vis[i] = 1;
if(x == k && prime(sum)) kase++;
else search(x + 1, i);
sum -= s[i]; vis[i] = 0;
}
}
}
int main() {
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> s[i];
search(1, 1);
cout << kase;
return 0;
}