P1036 选数
题目描述
已知 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,…,xn (1 < =xi <= 5000000)
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入
4 3
3 7 12 19
输出
1
代码的实现
#include<iostream>
#include<math.h>
using namespace std;
int s[100],dis[100],k,n,m;
int sum=0;
int judge(int x){ //函数判断是否为素数
if(x==1||x==0)return 0;
for(int i=2;i<=sqrt(x);i+=1)
if(x%i==0)
return 0;
return 1;
}
void dfs(int x,int y){ //递归函数,x控制m累加的个数,y控制m加的元素
for(int i=y;i<=n;i++){
if(!dis[i]){
dis[i]=1; //证明已经被选取过
m=m+s[i];
if(x==k){
if(judge(m))sum++; //如果等于k,判断m是否为素数,sum为出现情况的总数
}
else dfs(x+1,i+1); //递归实现下一个
m=m-s[i]; //回溯算法
dis[i]=0; //回溯,变回未被选取状态
}
}
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>s[i];
dis[i]=0;
}
dfs(1,1);
cout<<sum<<endl;
}
注意事项
递归算法的使用,一定要搞懂每个状态的变化,保持清醒的头脑。
体验回溯算法的用处,保证数据调用不会有某种情况未被发现。