NOIP 2002 选数

洛谷 P1036 选数

洛谷传送门

JDOJ 1297: [NOIP2002]选数 T2

JDOJ传送门

Description

​ 已知 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。

Input

n , k (1< =n< =20,k<n) x1,x2,…,xn (1< =xi< =5000000 )

Output

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

Sample Input

4 3 3 7 12 19

Sample Output

1

题解:

本题考查的知识点:递归生成全排列,质数判断。

递归生成全排列的相关知识:

相关知识—全排列传送门

相关知识—质数判断传送门

思路:

我们要枚举\(n\)数中\(k\)个数的全排列之和有多少是质数,需要生成全排列再判断一下质数即可,如果依次枚举无疑会超时,所以我们想出递归深搜来优化这个问题:

我们搜索的时候需要维护这么几个参数:首先是还剩多少个数没有选进去,然后是已经选进去的和是多少,最后是剩下数字的选取范围。

所以我们有如下的递归思路:

假如k==0,说明我们已经有了一个全排列,这时候需要判断,否则,就进入选取环节:从start到end枚举递归深搜,累加和。这样就得到了我们要求的答案。

代码:

#include<cstdio>
#include<cmath>
using namespace std;
int n,k;
int a[21];
bool check(int x)
{
    for(int i=2;i<=sqrt(x);i++)
        if(x%i==0)
            return 0;
    return 1;
}
int dfs(int k,int sum,int start,int end)
{
    if(k==0)
        return check(sum);
    int tot=0;
    for(int i=start;i<=end;i++)
        tot+=dfs(k-1,sum+a[i],i+1,end);
    return tot;
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    printf("%d",dfs(k,0,1,n));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fusiwei/p/11357604.html