题目描述
已知 n 个整数 x1,x2,…,xn,以及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=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
题解:
拿到题目的第一感觉就是DFS搜索。但紧接着遇到几个问题:第一、怎样搜索才能保证无重复?第二、怎样判断质数?
第一个问题有两种解决方式:第一种取数时升序,保证后取的数在先取的数前面,第二种状态压缩,用一个20位二进制数表示当前取数的状态,0位未取,1为取,然后开一个1500000左右大小的布尔数组记录状态是否被搜索过。第二个问题也有两种解决方式:第一种是最传统的质数判断方式,复杂度,第二种可以使用筛法筛出1~100000000的所有质数,形成质数表,
查询。计算可得,最极端的情况是20个数中取10个,也就是
种情况,每种情况判断最多需要
条左右,总共为
大于100000000,理论上不可行,正准备开始写线性筛的时候瞄了一眼难度,普及-。顿时醒悟:这题数据水啊!果断暴力
,于是,过了......
真的蛮想吐槽的,好好一道题,数据准备得这么水,真是可惜了。
代码:
#include<cstdio>
using namespace std;
const int maxn=25;
int n,k,sum,ans;
int number[maxn];
bool isprime(int x){//暴力
for (int i=2;i*i<=x;i++)
if (x%i==0) return false;
return true;
}
void DFS(int depth,int last){
if (depth==k){
if (isprime(sum)) ans++;
return ;
}
for (int i=last+1;i<=n;i++){
sum+=number[i];//sum也可以作为函数的传参,写法可能会简单点
DFS(depth+1,i);
sum-=number[i];
}
}
int main(){
// freopen("numbers.in","r",stdin);
// freopen("numbers.out","w",stdout);
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&number[i]);
DFS(0,0);
printf("%d",ans);
return 0;
}