Luogu洛谷 P1036选数
题目
题目链接
题解
这道题实际上是子集枚举的问题。
把n个数都存到1个数组里,那么需要枚举的是元素数量为k的子集,最求和判断是否为素数就可以。
子集枚举时候用2进制来表示每个元素的状态,1表示被选中,0表示未被选中。
n=4时,表示4个元素都被选中就是\(u=(1<<n)-1\)。
现在一个子集\(s=1011B\),如何检测第\(i(i\ge 0)\)个元素是否在子集中?
通过\(s \& (1<<i)\)来检测。这样做与运算,只有同为1才能返回1。
内建函数__builtin_popcount()可以返回二进制中1的数量。
所以程序思路为:枚举子集,当子集元素数量等于k时候,求和并检查是否为素数。
Then show the code.
#include <cstdio>
#include <iostream>
int n, k, x[30], sum, cnt;
bool check(int a){
for(int i=2; i*i<=a; i++){
if(a%i == 0) return 0;
}
return 1;
}
int main(){
scanf("%d%d", &n, &k);
for(int i=0; i<n; i++)
scanf("%d", &x[i]);
int u = (1<<n)-1;
for(int s=0; s<=u; s++){
if(__builtin_popcount(s) == k){
sum = 0;
for(int i=0; i<n; i++)
if(s & (1<<i)) sum += x[i];
if(check(sum)) cnt++;
}
}
printf("%d", cnt);
return 0;
}
不忘初心方得始终