题目描述
已知 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)
第二行 nn 个整数,分别为 x1,x2,⋯,xn(1 ≤ xi ≤ 5×10^6)
输出格式
输出一个整数,表示种类数。
输入输出样例
输入 #1复制
4 3 3 7 12 19
输出 #1复制
1
说明/提示
【题目来源】
NOIP 2002 普及组第二题
题解:题目n数据小于32可以用基本的二进制枚举,当然用dfs肯定可以,但是本人目前dfs还不熟练T_T,用了二进制枚举,效率也还可观。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[30],b[10000]={};
int prime(int n)
{
int i,flag,b;
flag=0;
b=(int)sqrt(n);//开方是为了防止时间超限 可以简化素数判定的时间!
for(i=1;i<b;i++)
{
if(n%(i+1)==0)
{
flag++;
return 0;
}
}
if(n==1)
{
return 0;
}
else if (flag==0)
return 1;
}
int main()
{
int n,k,i,j,s=0,count;
cin>>n>>k;
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<(1<<n);i++)//二进制枚举核心
{
count=0;
for(j=0;j<n;j++)
{
if(i>>j&1)//一位一位查看是否为 1
{
count++;
}
}
if(count==k)//判断题目条件
{
for(j=0;j<n;j++)
{
if(i>>j&1)
{
b[s]=b[s]+a[j];//求和
}
}
s++;
}
}
count=0;
for(i=0;i<s;i++)
{
if(prime(b[i]))
{
count++;
}
}
cout<<count;
return 0;
}