洛谷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<n1n20,k<n)

x_1,x_2,…,x_n (1 le x_i le 5000000)x1,x2,,xn(1xi5000000)

输出格式

屏幕输出,格式为: 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];
        }
    }
}
而递归函数则适用任何从多少个整数中挑选多少个数进行相加;

原文地址:https://www.cnblogs.com/zmz-zero/p/12260508.html