【洛谷】P1036 选数

洛谷P1036  选数

题目描述:

已知 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)

输出格式:

屏幕输出,格式为:

一个整数(满足条件的种数)。

 我认为这是一道很适合做DFS入门题的水题

这道题说白了就是一道暴力

但如何暴力,怎样的题该用暴力,这是不简单的

这道题能很好得让初学者认识到DFS并不仅仅局限于棋盘(个人经验)

 

算法思路如下:

其实很简单

暴力!暴力!暴力!

先确定第一个数,再向后枚举k-1个数

当累加到k个数时,判断一下和是否为质数

接着,开始回溯

到前一个转折点,再向后枚举“未走过的路”

当枚举到最后一个数时

转折点提前,继续枚举

若有更好见解,欢迎回复

 

以下代码仅供参考

#include<bits/stdc++.h>//万能头文件 
using namespace std;
int ans,n,k,a[50],i;
bool check(int a)//判断质数(a即为选择的k个数之和)
{
    int i;
    if(a<2) return false;
    for(i=2;i<=sqrt(a);i++)
    if(a%i==0) return false;
    return true;
}
void dfs(int num,int i,int sum)//(num表示已选数的个数,i表示下一个要枚举的数的位置,sum表示选数之和)
{
    if(num==k)//当选了k个数时
    {
        if(check(sum)) ++ans;//if所选数加起来是质数,ans累加
        return; //回溯
    }
    for(i;i<=n;i++)//只有这两行才是核心代码(其实就是一个暴力,相当于n个数中枚举k个元素的集合)
    dfs(num+1,i+1,sum+a[i]);//以i向后枚举,由于前一步处理了边界,这里不需担心会超过k个数
}

int main()
{
    cin>>n;
    cin>>k;
    for(i=1;i<=n;i++)
    cin>>a[i];
    dfs(0,1,0);//(从0个数开始,下一步枚举第一个数,累加器暂时为0)
    cout<<ans;//完美输出结果
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhouzhihao/p/9874026.html