题目连接:https://www.luogu.org/problemnew/show/P1036
题目描述
已知 n 个整数 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(1≤n≤20,k<n)
x1,x2,…,xn (1≤xi≤5000000)
输出格式:
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入样例#1: 复制
4 3 3 7 12 19
输出样例#1: 复制
1
详细题解在代码里
AC代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n, k, a[21], s, ans;
bool f[21];
int isprime(int n)//判断是否是质数的一个函数,不需多解释,i的范围到sqrt(n),是为了降低时间复杂度
{
for(int i = 2; i <= sqrt(n); ++i)
{
if(n%i == 0)
return 0;
}
return 1;
}
int rule(int x, int y)//x表示已经选了几个数,y为选第几个数,从y到n是为了避免重复的出现,例如1234中选3个,已经选了123
//与124,准备为13选下一个数,如果从1到n开始循环,则程序会到2,而2也是合适的,但这样就与123重复了,所以从y开始
{
for(int i = y; i <= n; ++i)
{
if(f[i] == true)//表示该数没有被选过,则执行if语句,
{
f[i] = false;//标志该数已经被选过,
s += a[i];//将对应的值加到s中
if(x == k)//当已经加到了k个,
{
if(isprime(s))//就判断这个和是否是质数,是的话那么就加1
ans += 1;
}
else//表示还没加到k个数,则继续搜寻下一个数,所以x+1,i+1是为了搜寻当前数的下一个数,避免重复,
rule(x+1, i+1);
s -= a[i];//回溯,s的值减去当前值a[i],这个语句要放在else之外,因为x==k时也无法继续搜寻,需要回溯,
f[i] = true;//标志为没有被选过
}
}
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);//依次读入这些数
f[i] = true;//标志为没有被选过
}
rule(1, 1);//从选了一个数,选第一个数开始调用函数
printf("%d\n", ans);//输出最终的结果,也就是多少个符合质数。
return 0;
}