洛谷p1036 选数解析
题目描述
已知 nn 个整数 x_1,x_2,…,x_nx1,x2,…,xn,以及11个整数kk(k<nk<n)。从nn个整数中任选kk个整数相加,可分别得到一系列的和。例如当n=4,k=3n=4,k=3,44个整数分别为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,k(1 \le n \le 20,k<n1≤n≤20,k<n)
x_1,x_2,…,x_n (1 \le x_i \le 5000000)x1,x2,…,xn(1≤xi≤5000000)
输出格式
屏幕输出,格式为: 11个整数(满足条件的种数)。
输入
4 3 3 7 12 19 |
输出
1 |
答案代码:
#include<iostream> #include<math.h> using namespace std; int a[20]; int n,k; bool isprime(int n){ //判断是否为素数 for(int i=2;i<=sqrt(double(n));i++){ //注意sqrt()里面必须是double类型 if(n%i==0) return false; } return true; } int xs(int k,int sum,int start,int end){ //选数,进行全组合,继而得出总数,进行判断 //k为要选择的数字的个数 //sum为所选数字的总和 //start为选择的第一个数(防止重复) //end为所给数的总数 if(k==0) { //当所选择的数的个数为0,选完所有的数之和,对这个数进行isprime(sum),即判断是否为素数,如果是返回false;否则返回true; // cout<<sum<<endl; return isprime(sum); //调用isprime函数判断是否为素数 } int s=0; for(int i=start;i<end;i++){ s+=xs(k-1,sum+a[i],i+1,end); //xs函数进行迭代,结束条件为k==0;并返回ture,或false,将如果是true,s+=1;否则s+=0; } return s; } int main(){ cin>>n>>k; for(int i=0;i<n;i++){ cin>>a[i]; } cout<<xs(k,0,0,n); return 0; }
结果:
上述迭代代码具体过程:
结果推导:
(1)调用: xs(3,0,0,n);
for(int i=0;i<n;i++){
s+=xs(2,a[i],i+1,n);
}
(2)二次调用函数 xs(2,a[i],1,n);
for(int i=i+1;i<n;i++){
s+=xs(1,a[i]+a[i+1];i+1+1,n);
}
(3)三次调用函数 xs(1,a[i]+a[i+1];i+1+1,n);
for(int i=i+1+1;i<n;i++){
s+=xs(0,a[i]+a[i+1]+a[i+1+1];i+1+1+1,n);
}
(4)四次调用函数 xs(0,a[i]+a[i+1]+a[i+1+1];i+1+1+1,n);
if(k==0) return isprime(sum);
由以上可知:调用了四次函数,第四次结束条件,从四个值中挑出三个相加
与下式相当:
for(int i=0;i<4;i++){
for(int j=i+1;j<4;j++){
for(int k=j+1;k<4;k++){
sum=a[i]+a[j]+a[k];
}
}
}
而递归函数则适用任何从多少个整数中挑选多少个数进行相加;