洛谷P1036 选数
题目描述:
已知 n 个整数 x1,x2,…,xn,以及一个整数 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)
输出格式:
屏幕输出,格式为:
一个整数(满足条件的种数)。
我认为这是一道很适合做DFS入门题的水题
这道题说白了就是一道暴力
但如何暴力,怎样的题该用暴力,这是不简单的
这道题能很好得让初学者认识到DFS并不仅仅局限于棋盘(个人经验)
算法思路如下:
其实很简单
暴力!暴力!暴力!
先确定第一个数,再向后枚举k-1个数
当累加到k个数时,判断一下和是否为质数
接着,开始回溯
到前一个转折点,再向后枚举“未走过的路”
当枚举到最后一个数时
转折点提前,继续枚举
若有更好见解,欢迎回复
以下代码仅供参考
#include<bits/stdc++.h>//万能头文件 using namespace std; int ans,n,k,a[50],i; bool check(int a)//判断质数(a即为选择的k个数之和) { int i; if(a<2) return false; for(i=2;i<=sqrt(a);i++) if(a%i==0) return false; return true; } void dfs(int num,int i,int sum)//(num表示已选数的个数,i表示下一个要枚举的数的位置,sum表示选数之和) { if(num==k)//当选了k个数时 { if(check(sum)) ++ans;//if所选数加起来是质数,ans累加 return; //回溯 } for(i;i<=n;i++)//只有这两行才是核心代码(其实就是一个暴力,相当于n个数中枚举k个元素的集合) dfs(num+1,i+1,sum+a[i]);//以i向后枚举,由于前一步处理了边界,这里不需担心会超过k个数 } int main() { cin>>n; cin>>k; for(i=1;i<=n;i++) cin>>a[i]; dfs(0,1,0);//(从0个数开始,下一步枚举第一个数,累加器暂时为0) cout<<ans;//完美输出结果 return 0; }