二进制枚举

已知n个整数x1, x2, .., xn,以及一个整数k,k < n。从n个数字

中任选k 个整数相加,可分别得到一系列的和。

例如当n = 4, k = 3,四个整数分别为3,7,12,19时,可得全部的组合与他们的和为:

3 + 7 + 12 = 22

3 + 7 + 19 = 29

7 + 12 + 19 = 38

3 + 12 + 19 = 34

现在,要求计算出和为素数的组合共有多少种。例如上例,只有一种组合的和为素数:3 + 7 + 19 = 29

1 n 20, k < n

1 x1, x2, .., xn 5 * 10^

 

 

首先我们来考虑如何枚举这样的组合。

我们用ai来表示第i个数是否被选:ai = 1表示这个数被选择了;ai =0表示这个数未被选择

枚举过程相当于枚举了一组二进制状态

比如对于五个数1,2,3,4,5

01010表示我们选择了2,4,未选择1,3,5 

 在不考虑k的限制的情况下,我们枚举所有组合就相当于枚举00..00(n0) 11..11(n1)

对于任意一种中间状态,0的个数+1的个数为n。

我们假设这是一个长为n的二进制数,我们将它转换成十进制。

事实上就是枚举了一个数,范围是[ 0, 2^)

判断位置i是否为1使用位运算来完成 

 

#include<iostream>
#include<cmath>
using namespace std;

int n,k;
int num[21];
int ans;

bool check( int n ){
    int t=sqrt(n);
    for( int i=2 ; i<=t ; ++i ){
        if( n%i==0 ) return 0;
    }
    return 1;
}

int main(){
    cin>>n>>k;
    for( int i=1 ; i<=n ; ++i ){
        cin>>num[i];
    }
    
    for( int i=0 ; i<( 1<<n ) ; ++i ){
        int tmp=0,sum=0;
        for( int j=0 ; j<n ; ++j ){
            if( (1<<j)&i ){
                tmp++;
                sum+=num[j];
            }
        }
        if( tmp==k ) ans+=check(sum);
    }
    
    cout<<ans;
    
    return 0;
}

 

 

posted @ 2019-04-28 20:43  莫瑞  阅读(737)  评论(0编辑  收藏  举报