选数【搜索 深度优先搜索,DFS 素数判断,质数,筛法】
[NOIP2002 普及组] 选数
题目描述
已知 n
个整数 x_1,x_2,\cdots,x_n
,以及 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
)。
第二行 n
个整数,分别为 x_1,x_2,````,x_n
(1 <= x_i <= 5*10^6
)。
输出格式
输出一个整数,表示种类数。
样例输入 #1
4 3
3 7 12 19
样例输出 #1
1
题目分析
主要是一个DFS深搜,要从n个数中找出任意k个数相加,计算其值是否为素数。
- 和排列组合为问题相似,n选3,n选n,有几种排列的方式
- 但是这个题要的是 k 个数,所以要使用 num 来计数
- 并且还需要用一个 for 循环来控制是否需要进入 dfs
程序如下:
#include<stdio.h>
int n,k,a[25],t;
int sushu(int b) {
int i;
if(b<2)
return 0;
for(i=2; i*i<=b; i++)
if(b%i==0)
return 0;
return 1;
}
void dfs(int num,int sum,int j) {
int i;
if(num==k) {//递归num次代表有num个数相加
if(sushu(sum))
t++;
return;
}
for(i=j; i<n; i++)
dfs(num+1,sum+a[i],i+1);//当i+1大于等于n时剪枝
return;
}
int main() {
int i;
scanf("%d %d",&n,&k);//输入n和k
for(i=0; i<n; i++) {
scanf("%d",&a[i]);//将n个数存放在a[]数组中
}
dfs(0,0,0);//(取到的个数,取到的数值和,剪枝条件)
printf("%d",t);
return 0;
}