洛谷:P1036:选数
题目描述
已知 nn 个整数 x1,x2,…,xnx1,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≤n≤20,k<n1≤n≤20,k<n )
x1,x2,…,xn(1≤xi≤5000000)x1,x2,…,xn(1≤xi≤5000000)
输出格式:
屏幕输出,格式为: 11 个整数(满足条件的种数)。
输入输出样例
题解:
感觉就是一个dfs的模板题,加上判断素数就可以了,整个题的数据量也不大,没有什么特别说明的。
附上代码(已AC)
1 #include <iostream> 2 using namespace std; 3 4 int n, k, x[21]={0}; 5 int sum=0, ans=0; 6 7 bool judge(int t){ #判断是否是素数 8 if(t==2) return true; 9 for(int i=2;i<t/2;i++){ 10 if(t%i==0) return false; 11 } 12 return true; 13 } 14 15 void dfs(int count, int pos){ #count是当前有几个数被计算了,pos是他们的位置 16 if(count > k){ 17 if(judge(sum)){ 18 ans++; 19 } 20 return; #回溯 21 }
22 else{ 23 for(int i=pos+1;i<=n;i++){ 24 sum += x[i]; 25 dfs(count+1, i); 26 sum -= x[i]; 27 } 28 } 29 } 30 31 int main(){ 32 cin >> n >> k; 33 for(int i=1;i<=n;i++) cin >> x[i]; 34 dfs(1,0); 35 cout << ans; 36 return 0; 37 }
dfs模板(伪代码):
1 void dfs()//参数用来表示状态 2 { 3 if(到达终点状态) 4 { 5 ...//根据题意添加 6 return; 7 } 8 if(越界或者是不合法状态) 9 return; 10 if(特殊状态)//剪枝 11 return ; 12 for(扩展方式) 13 { 14 if(扩展方式所达到状态合法) 15 { 16 修改操作;//根据题意来添加 17 标记; 18 dfs(); 19 (还原标记); 20 //是否还原标记根据题意 21 //如果加上(还原标记)就是 回溯法 22 } 23 24 } 25 }