洛谷OJ P1036 选数

  • 题目描述已知 nnn 个整数 x1,x2,…,xnx_1,x_2,…,x_nx1​,x2​,…,xn​,以及111个整数kkk(k<nk<nk<n)。从nnn个整数中任选kkk个整数相加,可分别得到一系列的和。例如当n=4,k=3n=4,k=3n=4,k=3,444个整数分别为3,7,12,193,7,12,193,7,12,19时,可得全部的组合与它们的和为:3+7+12=223+7+12=223+7+12=223+7+19=293+7+19=293+7+19=297+12+19=387+12+19=387+12+19=383+12+19=343+12+19=343+12+19=34。现在,要求你计算出和为素数共有多少种。例如上例,只有一种的和为素数:3+7+19=293+7+19=293+7+19=29。输入格式键盘输入,格式为:n,kn,kn,k(1≤n≤20,k<n1 \le n \le 20,k<n1≤n≤20,k<n)x1,x2,…,xn(1≤xi≤5000000)x_1,x_2,…,x_n (1 \le x_i \le 5000000)x1​,x2​,…,xn​(1≤xi​≤5000000)输出格式屏幕输出,格式为: 111个整数(满足条件的种数)。

  • 输入格式
    在这里插入图片描述

  • 输出格式
    在这里插入图片描述

  • 基本思路

  • 一次选一个数,注意按照升序来选(因为是组合不是排列,避免最终选出的数集重复),采用递归的方式,每选完一个数在调用自身选下一个数,直到递归出口(全部选完)

  • 程序清单

#include<stdio.h>
#include<math.h>
#include<stdbool.h>
int a[20+5]; //数组下标代表数在数组中的位置 
int amt; 
int n,k,js=0;
bool isprime(int x);
void sort(int w,int m); //从上一个数(第w-1个数,位置在m处)开始往后选出下一个数(第w个数)并加入总和,保证不重样 
int main()
{
 scanf("%d%d",&n,&k);
 for(int i=0;i<n;i++)  //输入第0到第n-1共n个数(位置即0到n-1) 
 {
  scanf("%d",&a[i]);
 }
 sort(1,-1); //开始选第一个数,缺省第一个数的上一个数位置为-1 
 printf("%d",js); 
    return 0;
}
bool isprime(int x) //判断素数 
{
 for(int i=2;i<(int)(sqrt(x))+1;i++)
 if(x%i==0&&x!=2) return false;
 return true;
}
void sort(int w,int m)//从上一个数(第w-1个数)的位置m开始选出下一个数(第w个数)并加入总和,保证不重样
{
 if(w-1==k) //判断上一步执行后是否全部选完了 
 {
  if(isprime(amt)) js++;
  return;
 } //全部选出的情况下,如果和为素数则计数加一,否则返回上一步 
 else //直到上一步还没选完,接着选 
 {
  for(int i=m+1;i<=n-1;i++) //从上一个数(位置m)的下一位(位置m+1)开始选,不行就换下下位,依此类推 
  {
   amt+=a[i]; //将这次选出来的数计入总和 
   sort(w+1,i); //选下一个数 
   amt-=a[i]; //每次选完后面的数之后,退回这次选的数 
  } 
 }
 return; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值