洛谷递归刷题日记.5

82 阅读2分钟

P1036 [NOIP 2002 普及组] 选数

题目描述

已知 nn 个整数 x1,x2,,xnx_1,x_2,\cdots,x_n,以及 11 个整数 kkk<nk<n)。从 nn 个整数中任选 kk 个整数相加,可分别得到一系列的和。例如当 n=4n=4k=3k=344 个整数分别为 3,7,12,193,7,12,19 时,可得全部的组合与它们的和为:

3+7+12=223+7+12=22

3+7+19=293+7+19=29

7+12+19=387+12+19=38

3+12+19=343+12+19=34

现在,要求你计算出和为素数共有多少种。

例如上例,只有一种的和为素数:3+7+19=293+7+19=29

输入格式

第一行两个空格隔开的整数 n,kn,k1n201 \le n \le 20k<nk<n)。

第二行 nn 个整数,分别为 x1,x2,,xnx_1,x_2,\cdots,x_n1xi5×1061 \le x_i \le 5\times 10^6)。

输出格式

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

输入输出样例 #1

输入 #1

4 3
3 7 12 19

输出 #1

1

说明/提示

这依旧是个递归的题 但我们可以发现当n相同 而k相近时 只要给到的x不一样那么这个数据之间就不会存在递推 那么我们应该怎么办呢 考虑到这个n最大只有20 我们不妨来试试暴力枚举 而这个枚举本身也是一种递推 我们让x1当排头然后x2再当排头就这样不断下去就可以模拟完所有情况了 所以代码如下

#include <stdio.h>
int arr[25];//把数组定义为全局变量 方便我们后面的调用
int n,num;同理
int count=0;//计数器
bool Isshu(int n){
if(n==1){return false;}
else if(n==2){return true;}
else if(n%2==0){return false;}
else {   
    for(int i=2;i*i<=n;i++){
      if(n%i==0){return false;}
    }
    return true;
  }
}//判断是不是素数
void ans(int begin,int k,int sum){
    if(k==0){
    if(Isshu(sum)){count++;}
    return ;//当我们所需要的数量变成0后 我们就开始判断是不是素数了 就可以反会了
    }
    if(begin-n+1<k){return ;}//如果我们剩下的树都不足以拿出来凑满 那么可以直接退出了
    for(int i=begin,i<n,i++){
      ans(begin+1,k-1,sum+arr[i]);//用下一个函数来判断而不是当前函数来判断可以保证每次的sum都不会一直积累
      }
}
int main(){
scanf("%d %d",&n,&num);
for(int i=0;i<n;i++){
  scanf("%d",&arr[i]);
}
ans(0,num,0);
printf("%d",count);
return 0;
}