P1036 选数【暴力枚举、dfs】
题目描述
已知 nn 个整数x1,x2,…,xn,以及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(k<n1≤n≤20,k<n)
x1,x2,…,xn(1≤xi≤5000000)
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入
4 3
3 7 12 19
输出
1
解题思路
这里给我们的数并不多,n<=20,因此我们可以采用遍历所有组合情况后判断其和是否为素数。
这里我采用dfs的方法,不过需要注意的是,这里组合时每个数只能使用一次,所以我在遍历时采用如下代码:
for (int i = s; i <= n; i++)
{
dfs(cnt + 1, sum + arr[i], i + 1);
}
其中这里的s就是上一层dfs里的i+1,每次从上一层选用的数的后面开始继续遍历,这样保证每个数只使用1次(这里也可以采取回溯的方法)。
代码
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
#define ll long long
ll arr[25];
int n, k;
int ans = 0;
int isPrime(ll sum)
{
for (int i = 2; i <= sqrt(sum); i++)
{
if (sum%i == 0)
return 0;
}
return 1;
}
void dfs(ll cnt, ll sum, int s)
{
if (cnt == k)
{
if (isPrime(sum))
ans++;
}
else
{
for (int i = s; i <= n; i++)
{
dfs(cnt + 1, sum + arr[i], i + 1);
}
}
}
int main()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
}
int vis[25] = { 0 };
dfs(0, 0, 1);
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号