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;
}

 

posted @ 2020-06-13 09:06  Hu_YaYa  阅读(19)  评论(0)    收藏  举报