题目描述
已知 n 个整数 x1,x2,⋯,xn,以及 1 个整数 k(k<n)。从 nn 个整数中任选kk 个整数相加,可分别得到一系列的和。例如当n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
输入格式
第一行两个空格隔开的整数 1≤n≤20 k<n)。
第二行 n 个整数,分别为 x1,x2,⋯,xn( 10^6≤xi≤5×10^6)。
输出格式
输出一个整数,表示种类数。
输入输出样例
输入 #1复制
4 3 3 7 12 19
输出 #1复制
1
说明/提示
【题目来源】
NOIP 2002 普及组第二题
了解位运算戳以下链接
#include<bits/stdc++.h>
//#define __builtin_popcount __popcnt VS上实现需要加此条预编译指令
using namespace std;
int a[20];
bool check(int x) {//检查是否为素数
for (int i = 2; i * i <= x; i++){//这样比调用sqrt函数更快
if (x % i == 0)return false;
}
return true;
}
int main(){
int n, k,ans=0;
cin >> n >> k;
for (int i = 0; i < n; i++)cin >> a[i];
int U = 1 << n;//U-1为全集,左移后第n+1位为1,其他都为0,所以U-1所有位都变成1
for (int s = 0; s < U; s++) {
if (__builtin_popcount(s) == k) {//如果s的二进制位中有k个1
int sum = 0;
for (int i = 0; i < n; i++)
if (s & (1 << i))sum += a[i];//1左移i位后,只有第i+1位(下标位i)为1,其他位都为0,s&,利用&运算,&1则不变,&0都为0
//如果下标为i的数字在“集合”内,&运算后结果不为0,否则为0,因此可用来检查
if (check(sum))ans++;//如果是素数总数就++
}
}
cout << ans;
return 0;
}