选数(c++)

已知 n 个整数 x1,x2,⋯,xn,以及 1 个整数 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)。

第二行 n 个整数,分别为 x1​ ,x2​ ,⋯,xn(1≤x i​ ≤5×pow(10, 6) )。

输出格式
输出一个整数,表示种类数。

输入输出样例
输入1

4 3
3 7 12 19

输出1

1

解释说明:

输入 4 3,表示一共 4 个整数,从中 3 个整数相加,第二行即为需要进行计算的数值,可得出:

3+7+12=22

3+7+19=29

7+12+19=38

3+12+19=34

由此判断上述结果中为素数的个数,此例中只有 3+7+19=29 为素数,所以输出个数 1。

【来源】
NOIP 2002 普及组第二题

//使用深度优先搜索

//代码如下:

#include <iostream>

#include <vector>

using namespace std;

int n,k;

vector<int>num;

int res=0;

vector<int>temp;

//判断是不是素数

int isprime(int num){

    for(int i=2;i*i<=num;i++){

        if(num%i==0)

        return 0;

    }

    return 1;

}

//枚举,按照字典序号进行排序

void dfs(int index,int start,int sum){

    //index正在选择第index个数字位置

    //start往后选择

    //sum计算所选数字的和

    if(index==k){

        if(isprime(sum)){

        res++;

        }

        return;

    }

/核心代码

    if(start<n){

        //选择

        dfs(index+1,start+1,sum+num[start]);

        //不选择

        dfs(index,start+1,sum);

    }

//核心代码

/*

核心代码等价于下面这段代码

for(int i=start;i<n;i++)

        dfs(index+1,i+1,sum+num[i]);

*/

}

int main(){

    cin>>n>>k;

    for(int i=0;i<n;i++){

        int number;

        cin>>number;

        num.push_back(number);

    }

    dfs(0,0,0);

    cout<<res<<endl;

    return 0;

}

//第二种解法

/*

#include <iostream>

#include <vector>

#include <algorithm>

#include <iomanip>

using namespace std;

#define MAXSIZE 100

int n,k;

bool pos[MAXSIZE];

vector<int> res;

int *data;

int cnt=0;

//组合问题

//判断是不是素数

int isprime(int sum) {

    for(int i=2;i*i<sum;i++)

    if(sum%i==0)

    return 1;

    return 0;

}

void dfs(int start,int index){

    //start数组下标起点

    //index取了几个数字

    if(index==k){

        int sum=0;

        for(int i=0;i<res.size();i++)

        {           sum+=res[i];

        }

        if(!isprime(sum))cnt++;

        return;

    }

   

    for(int i=start;i<n;i++){

            res.push_back(data[i]);

            //选择

            dfs(i+1,index+1);

            res.pop_back();

        }

   

}

int main(){

    cin>>n>>k;

    data=(int*)malloc(n*sizeof(int));

    for(int i=0;i<n;i++)

    cin>>data[i];

   

   

    dfs(0,0);

    cout<<cnt<<endl;

   

    free(data);

    return 0;

}

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值