题目来源:洛谷P1036https://www.luogu.com.cn/problem/P1036
题目描述
已知 n 个整数 x1,x2,…,xn 以及11个整数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个整数(满足条件的种数)。
输入输出样例
输入 1
4 3 3 7 12 19
输出 1
1
思路
先举个例子,从1,2,3,4,5,6 这6个数中选3个数组合,按照题意一个组合中不能出现重复的数,按顺序枚举:
第一轮:
1 2 3
1 2 4
1 2 5
1 2 6
第二轮:
1 3 4
1 3 5
1 3 6
…………
第二轮 1 3 x ,第三个数直接从4开始枚举,不重复枚举
同理,第三轮 1 4 x ,x从5开始枚举……
用index记录下一次搜索的开始位置
AC代码
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
int n,k;
ll a[25];
ll b[25]; //记录组合的数
ll cnt = 0; //记录质数个数
//判断一个数是否为质数
bool isPrime(int n)
{
//for(int i=2;i*i<=a;i++)
for(int i=2;i<=sqrt(n);i++){
if(n%i == 0) return false;
}
return true;
}
//递归,pos记录组合数个数,index记录开始搜索的位置
void dfs(int pos,int index)
{
int sum; //k个数之和
for(int i=index;i<n;i++){
b[pos] = a[i];
//数没找够,index=i+1从下一个数开始搜索
if(pos < k-1) dfs(pos+1,i+1);
//已经找够了k个数
if(pos == k-1){
sum = 0; //初始化
for(int j=0;j<k;j++) sum += b[j];
//sum当前组合的数总和为质数,cnt+1
if(isPrime(sum)) cnt++;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
dfs(0,0);
cout<<cnt;
return 0;
}