P1036 选数

题目描述

https://www.luogu.com.cn/problem/P1036

从nn个整数中任选kk个整数相加,可分别得到一系列的和。例如当n=4,k=3 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=293+7+19=29。

思路说明

这条题目是一条求组合的题目,组合在计算机上面,一般用递归处理,以n=5, k=2为例,假设数据为 1 2 3 4 5。
先选第一个数字:
第一个数字选择1,然后再 2 3 4 5里面再进行求组合的计算,这很显然是一个递归过程,递归的出口是k=1
第一个数字选择2,然后再在3 4 5里面再进行求组合的计算,显然又是一个递归过程,递归的出口仍然是k=1
...
依次的,直到每个数字都选完

代码

#include <iostream>
#include <cmath>

using namespace std;

int is_prime(int n)
{
	int i;
	int s = sqrt(n);

	if(n == 1)
		return 0;

	for(i=2; i<=s; i++) {
		if(n % i == 0) {
			break;
		}
	}

	return i > s;
}

void _get(int *array, int *visit, int l, int n, int k, int *sum)
{
	if(k == 1) {
		int tmp = 0;

		visit[l] = 1;

		for(int i=0; i<n; i++) {
			if(visit[i]) {
				tmp += array[i];
			}
		}

		if(is_prime(tmp)) {
			*sum += 1;
		}

		visit[l] = 0;

		return;
	}

	visit[l] = 1;

	for(int i=l+1; i<n; i++) {
		_get(array, visit, i, n, k-1, sum);
	}

	visit[l] = 0;
}

int get(int *array, int n, int k)
{
	int *visit = new int[n]();
	int sum = 0;

	for(int i=0; i<n; i++)
	{
		_get(array, visit, i, n, k, &sum);
	}

	delete [] visit;

	return sum;
}

int main(int argc, char **argv)
{
	int n,k;
	int *array;

	while(cin >> n >> k) {
		array = new int [n];

		for(int i=0; i<n; i++) {
			cin >> array[i];
		}

		cout << get(array, n, k) << endl;

		delete [] array;
	}

	return 0;
}

posted @ 2020-02-02 16:01  joechow  阅读(137)  评论(0)    收藏  举报