已知 n 个整数 x1,x2,…,xn,以及一个整数 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
第二行为空格分开的n个数,分别表示x1,x2,...,xn
输出格式
一个整数,表示满足条件的种数
样例输入
4 3
3 7 12 19
样例输出
1
数据规模和约定
1<=n<=20,k<n
1<=xi<=5000000
在讲解此题之前,我们先来看看全部组合问题的模板(这里如果像<< >> & 等位符号还不懂的,建议先去学习一下,不然看不懂下面的解释的
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,x,ct=0,d[25];
void jh(int n){
for(int i=0;i<(1<<n);i++){
for(int j=0;j<n;j++){ //输出
if(i&(1<<j))cout<<d[j]<<" ";
//这里假设n=4,那么就是j== 1 10 100 1000 i=0000(空集) i==0001 0010 0011 0100 0101 ...
}
cout<<endl;
}
}
signed main(){
cin>>n>>k;
for(int i=0;i<n;i++)d[i]=i;
jh(n);
}
这里采用二进制输出所有组合数,我们可以发现,用二进制的1来配对数据,举个例子
比如n=4,2^4=16,也就是10000,但我们这里减个1的话就是15,15的二进制是1111,那么从0000-1111每次都和0001,0010,0100,1000进行配对,不就是所有组合(也就是集合的个数)了吗,那么下面给出部分的演示
i=0000 每次和 j=0001,0010,0100,1000 进行配对(i&(1<<j)),可以发现,一个都配对不了,也就是集合中的空集
i=0001 每次和 j=0001,0010,0100,1000 进行配对(i&(1<<j)) 可以发现 只有0001可以配对成功,此时j=0,也就是(1<<j)=>1*2^0=>1 这个1就是0001
i=0010 每次和 j=0001,0010,0100,1000 进行配对(i&(1<<j)) 可以发现 只有0010可以配对成功,此时j=1,也就是(1<<j)=>1*2^1=>2 这个2就是0010
..........
i=1011 每次和 j=0001,0010,0100,1000 进行配对(i&(1<<j)) 可以发现,0001 0010 1000三个都可以配对成功 也就是当i=1011的时候,j输出当j=0001 0010 1000的值,这里的组合就是d[0],d[1],d[3]
以此类推,可能有人看到这里,还是一脸懵逼,其实就是,i的二进制中的每个1,代表集合中对应的值,也就是对应的d的下标。
上面的也是模板,是输出全组合的模板代码
那么步入正题,题目要我们输出C(n,k)的部分组合,怎么办?
这里我们首先在来学习一个神奇的操作,k=k&(k-1),这个操作是什么意思呢?就是输出k的二进制中1的个数,如果想知道这个原理的,我另外一个文章有讲解,那么知道1的个数后,按照上面的代码思路,如果1的个数等于题目中的k,那不就可以求出C(n,k)的各个值了吗
我们直接看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,x,ct=0,d[25];
bool zs(int n){
for(int i=2;i<=sqrt(n);i++){
if(n%i==0)return 0;
}
return 1;
}
void jh(int n){
for(int i=0;i<(1<<n);i++){
int num=0,kk=i;
while(kk){
kk=kk&(kk-1);
num++;
}
if(num==k){
int sum=0;
for(int j=0;j<n;j++){
if(i&(1<<j))sum+=d[j];
}
if(zs(sum))ct++;
}
}
}
signed main(){
cin>>n>>k;
for(int i=0;i<n;i++)cin>>d[i];
jh(n);
cout<<ct;
}
这个代码是题目的AC代码,把有关题目元素的代码删除后,也就是求部分组合的模板代码,k由num进行统计判断