题目描述

已知 n 个整数 x_1,x_2,…,x_nx1,x2,,xn,以及11个整数k(k<nk<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。例如当n=4,k=3 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,1n20,k<n)

x_1,x_2,…,x_n (1 <= x_i <= 5000000)x1,x2,,xn(1xi5000000)

输出格式

屏幕输出,格式为: 11个整数(满足条件的种数)。

 

这题真正的让我对dfs有个初步的了解,真的。

这题需要没有遗漏的选出任意k个数之和的所有情况,如果k是个确定的数,我们完全可以用k重循环来解决这道题,然而并非如此,我们想到,循环和递归是互通的,我们不能控制有多少重循环,却可以控制递归的次数。话不多说,上代码。

#include <iostream>
using namespace std;
long long ans = 0;
int a[25], n, k;

//判断是否为质数
bool is_prime(int x)
{
    for (int i = 2; i * i <= x;i++) if(x%i == 0)
            return false;
    return true;
}

//利用深度优先搜索进行搜索
void dfs(int cnt, int sum, int s)
//cnt为计数器,当cnt等于k时,递归结束。
//sum为当前所加数之和
//s为起始下标
{
    if(cnt == k) {
        //判断和是否为质数
        if(is_prime(sum))
            ans++;
        return;//递归结束
    }
    for (int i = s; i < n;i++)
        dfs(cnt + 1, sum + a[i], i + 1);
//每加一次,计数器加一,自底而上的加,防止遗漏
}

int main()
{
    cin >> n >> k;
    for (int i = 0; i < n;i++)
        cin >> a[i];
    dfs(0, 0, 0);//初始化
    cout << ans << endl;
    return 0;
}

原文链接:https://www.luogu.com.cn/problemnew/solution/P1036

原创作者:东北小蟹蟹