洛谷题解:P1036 [NOIP2002 普及组] 选数
题目:
已知 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<n1)
x1,x2,…,xn(1≤xi≤5000000)
输出格式:
屏幕输出,格式为: 1个整数(满足条件的种数)。
扫描二维码关注公众号,回复:
12916365 查看本文章
样例:
输入:
4 3
3 7 12 19
输出:
1
分析:
这道题需要通过dfs去遍历三个不同元素的组合,最后再用单个的普通筛法筛取素数。
下面解释一下dfs搜索的方法。
一个最多20个数,每一次循环为1或0的循环,即表示这个数是否被选择。
搜索停止的条件就是元素满足三个的时候,即return;
,我忘了。return;
debug了近半个多小时…血亏
然后循环次数达到元素个数的时候也停止搜索。
筛法就是普通筛法,数据组数很少。
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int n,k;
long long a[100];
long long sum[100];
long long num = 0;
long long Sum = 0;
long long judge = 1;
long long jie = 1;
int q = 0;
void dfs(int now)
{
if(num == k)
{
sum[q++] = Sum;
return;
}
if(now == n)
{
return;
}
for(int i = 1;i >= 0;i--)
{
if(i)
{
Sum += a[now];
num++;
dfs(now + 1);
Sum -= a[now];
num--;
}
else
{
dfs(now + 1);
}
}
}
bool isprime(long long x)
{
for(long long i = 2;i <= sqrt(x);i++)
{
if(x % i == 0)
{
return false;
}
}
return true;
}
int main()
{
cin>>n>>k;
int temp = n;
int temp2 = k;
int ans = 0;
for(int i = 0;i < k;i++)
{
judge = judge * temp--;
jie = jie * temp2--;
}
judge = judge / jie;
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i = 0;i < n;i++)
{
cin>>a[i];
}
dfs(0);
for(int i = 0;i < q;i++)
{
if(isprime(sum[i]))
{
ans++;
}
}
cout<<ans<<endl;
return 0;
}