LUOGU P1036 选数

LUOGU P1036 选数_第1张图片

题目描述
已知 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 (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)

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

输入输出样例
输入样例#1

4 3
3 7 12 19                    

输出样例#1

1

思路:
这是一道很经典的深搜题目,看到很多神犇用递归(递推)做,其实没必要,直接用dfs暴力解决就可以了。
首先,我们写一个dfs函数,赋予三个变量,分别为step, sum, cnt。 我们用step 来记录当前选的是第几个数,sum 是这个数,cnt是已选的可行的数。(这个地方大家好好揣摩一下cnt 和 step 的区别。同时,我们可以用一个a数组来记录我们所选的数。最后进行素数判断,用sqrt的朴素版即可。(不会TLE)

代码:

#include
#include
#include  //sqrt()的函数库
using namespace std;
int a[10001];  //记录所选的数
int n,k,sum,total;  //total为总方案数
inline void print()  //打印函数(依照个人习惯)
{
    printf("%d",total);
}
inline bool prime(int x)  //素数判断
{
    for(register int i=2;i<=sqrt(x);i++)
        if(x%i==0)
            return false;
    return true;
}
inline void dfs(int step,int sum,int cnt)
{
    if(step==n+1||cnt==k)  //如果已经进行到了n+1次,或者是已经选了k个数
    {
        if(prime(sum) && cnt==k)  //如果sum为一个素数且已经选了k个数
            total++;  //总方案书+1
        return;  //返回
    }
    dfs(step+1,sum+a[step],cnt+1);  //继续搜索,选择下一个数
    dfs(step+1,sum,cnt);  //继续枚举不选择下一个数的情况
    return;
}
int main()
{
    scanf("%d %d",&n,&k);
    for(register int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    dfs(1,0,0);  //从第个数开始搜
    print();  //最后打印结果
    return 0;
}

你可能感兴趣的:(c++,dfs,题解-洛谷)