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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具