20241124每日一题洛谷P1036

普及-每日一题洛谷P1036

题目描述

已知 \(n\) 个整数 \(x_1,x_2,\cdots,x_n\),以及 \(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 \le n \le 20\)\(k<n\))。

第二行 \(n\) 个整数,分别为 \(x_1,x_2,\cdots,x_n\)\(1 \le x_i \le 5\times 10^6\))。

输出格式

输出一个整数,表示种类数。

样例输入

4 3
3 7 12 19

样例输出

1

经典的DFS搜索问题,从 \(n\) 个数中选出 \(k\) 个数,使他们的和为素数,计算素数的个数

因为每个数只能选一次,而且计算的是他们的和,所以选数的顺序没有区别

就要做到不重不漏,我们每次搜索下一个数时,就要从前一个数之后开始寻找:

void dfs(int x,int st){//x表示当前我们考虑的是第几个组合数,st表示这次选数从多少开始选
if (x>k){//当我们考虑到第k个组合数之后时,触碰到边界返回
if (prime(sum))//如果是素数,答案加1
ans++;
return ;
}
for (int i=st;i<=n;i++){//从第st个数开始往后查找
sum+=a[i];//计算组合数之和
dfs(x+1,i+1);//递归查找第x+1个组合数
sum-=a[i];//回溯复位
}
}

因为每次都从上一个组合数之后的数开始查找,我们选出来的数构成了一个下标严格单调递增的序列

该序列的元素不会重复,即不会回头选我们前面已经选过了的数,组合方案有 \(C_k^n\)

完整代码:

#include <stdio.h>
int n,k,sum,ans;
int a[22];
bool prime(int x){
if (x==2) return 1;
if (x%2==0) return 0;
for (int i=2;i<=x/i;i++)
if (x%i==0) return 0;
return 1;
}
void dfs(int x,int st){
if (x>k){
if (prime(sum))
ans++;
return ;
}
for (int i=st;i<=n;i++){
sum+=a[i];
dfs(x+1,i+1);
sum-=a[i];
}
}
int main()
{
scanf("%d %d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
dfs(1,1);
printf("%d",ans);
return 0;
}
posted @   才瓯  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示