递归选数问题
题目描述
已知 n个整数 x1,x2,…,xn,以及1个整数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,…,x**n(1≤x**i≤5000000)
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入 #1
4 3
3 7 12 19
输出 #1
1
解题思路
首先需要一个子函数判断一个数是否为素数,让该数x从2到根号x取余,若全部结果不为0,则是素数,否则不是。
然后就可以开始递归选数了,初始先将所有的数标记位记为0,表示没选。
int dg(int num,int sum)
递归,num表示取第几个数,sum表示取了几个数。
从num开始遍历,如果当前数还没被选过,就选它,然后把它标记为已选过;将当前选的数累和,如果已经取够要求数量的数,就判断和是否为素数,如果是,最终结果+1。
若还没取够,则递归继续选数dg(i+1,sum+1)
完整代码
#include <bits/stdc++.h>
using namespace std;
int n,k;
int a[100];
int res;//最终结果
int b[100];//标记当前数是否被选过
int s; //当前所选的数的和
int sushu(int x)//判断 x是否为素数
{
for(int i=2;i<=sqrt(x);i++)
{
if(x%i!=0) return 0;
}
return 1;
}
int dg(int num,int sum)//递归取数,num表示取第几个数,sum表示取了几个数
{
for(int i=num;i<n;i++)
{
if(b[i]==0)//如果还没被选过
{
b[i]=1;//选它,并标记为选过
s+=a[i];//累和
if(sum==k)//如果已经取够要求的数量
{
if(sushu(s)) res++;//判断和是否为素数,是的话最后结果 +1
}
else dg(i+1,sum+1);//否则继续选数
s-=a[i];//回溯
b[i]=0;
}
}
}
int main()
{
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>a[i];
dg(0,1);//初始选一个数,从 a[0]开始
cout<<res;
return 0;
}