P1036 [NOIP 2002 普及组] 选数
记录140#includebits/stdc.h using namespace std; const int N25; // 定义常量N表示n的最大范围题目n20 int n,k; // n表示整数个数k表示需要选出的个数 int a[N]; // 记录n个整数 int ans0; // 记录和为素数的组合种类数 // 判断一个数x是否为素数 bool is_prime(int x){ if(x2) return false; // 小于2的数不是素数 for(int i2;i*ix;i){ if(x%i0) return false; // 如果能被i整除不是素数 } return true; // 是素数 } // 深度优先搜索DFS // start: 当前从第几个数开始选保证组合不重复且有序 // cur: 当前已经选了几个数 // sum: 当前已选数的总和 void dfs(int start,int cur,int sum){ if(curk){ // 如果已经选够了k个数递归终止条件 if(is_prime(sum)) ans; // 判断总和是否为素数,种类数加1 return; // 结束当前递归分支 } // 可行性剪枝剩下的数必须足够凑齐k个 // 当前从start开始选还需要选(k-cur)个数所以i的上限是 n-(k-cur)1 // 循环终点 总数 - 还需要选的个数 1 for(int istart;in-(k-cur)1;i){ dfs(i1,cur1,suma[i]); // 从下一个位置开始选已选数量1总和加上a[i] } } int main(){ // 主函数入口 ios::sync_with_stdio(false); // 关闭标准流同步提升输入输出效率 cin.tie(0); // 解除cin与cout的绑定加快读取速度 cinnk; // 读入n和k for(int i1;in;i) cina[i];// 读入n个整数 dfs(1,0,0); // 从第1个数开始选当前选了0个当前总和为0 coutans; // 输出和为素数的组合种类数 return 0; // 程序正常结束 }题目传送门https://www.luogu.com.cn/problem/P1036前言我是一名专注信奥赛CSP-J/S、NOIP的教练。如果你觉得这篇题解对你有帮助欢迎点击关注我的CSDN账号我会持续更新高质量算法解析。我深知算法思维的构建远比单纯通过题目更重要本系列题解不局限于AC代码的堆砌而是致力于拆解题目背后的逻辑链条与核心知识点备赛路上若遇瓶颈欢迎随时评论或私信我将甄选典型疑难问题通过视频讲解或撰写专项文章的形式为你提供深度答疑。核心解题思路这道题是一道非常经典的组合枚举与素数判定问题。问题转化题目要求从 n个整数中任选 kk 个相加统计和为素数的组合种类数。这本质上是一个“从 n 个数中取 k 个数的组合问题”即 Cnk 而不是排列问题。因为加法满足交换律3719和7319是同一个组合我们需要避免重复计算。算法选择DFS 剪枝由于 n≤20 数据规模较小我们可以使用深度优先搜索DFS来暴力枚举所有可能的组合。避免重复在 DFS 过程中我们通过一个start参数来记录当前从哪个位置开始选数。每次递归选择下一个数时都从当前位置的下一个位置i1开始选从而保证选出的数在原数组中的下标是严格递增的天然避免了组合的重复。可行性剪枝在枚举当前层的选择时如果剩下的数字个数不足以凑齐 kk 个数就提前停止枚举减少无效搜索。素数判定当凑齐 kk 个数时计算它们的和并使用试除法判断该和是否为素数。代码分块详细解释1. 头文件、常量与全局变量定义#includebits/stdc.h using namespace std; const int N25; // 定义常量 N表示 n 的最大范围题目 n20 int n,k; // n 表示整数个数k 表示需要选出的个数 int a[N]; // 记录 n 个整数 int ans0; // 记录和为素数的组合种类数详细分析这部分定义了算法的基础变量。a[N]用来存储输入的 nn 个整数ans作为全局计数器用来累加满足条件的组合数。2. 素数判定函数is_prime// 判断一个数 x 是否为素数 bool is_prime(int x){ if(x2) return false; // 小于 2 的数不是素数 for(int i2;i*ix;i){ if(x%i0) return false; // 如果能被 i 整除不是素数 } return true; // 是素数 }详细分析这是一个标准的试除法求素数函数。边界处理首先排除了小于 2 的情况因为 0 和 1 不是素数。循环优化循环的终止条件是i*i x即 i≤xi≤x​ 。这是因为如果 xx 有一个大于 xx​ 的因子那么它必然有一个小于 xx​ 的对应因子。这种优化将素数判定的时间复杂度从 O(x)O(x) 降低到了 O(x)O(x​) 对于本题中可能达到 5×106×205×106×20 级别的和来说效率提升非常明显。3. 核心逻辑DFS 组合枚举与剪枝// 深度优先搜索DFS // start: 当前从第几个数开始选保证组合不重复且有序 // cur: 当前已经选了几个数 // sum: 当前已选数的总和 void dfs(int start, int cur, int sum){ if(curk){ // 如果已经选够了 k 个数递归终止条件 if(is_prime(sum)) ans; // 判断总和是否为素数,种类数加 1 return; // 结束当前递归分支 } // 可行性剪枝剩下的数必须足够凑齐 k 个 // 当前从 start 开始选还需要选 (k-cur) 个数所以 i 的上限是 n-(k-cur)1 // 循环终点 总数 - 还需要选的个数 1 for(int istart; in-(k-cur)1; i){ dfs(i1, cur1, suma[i]); // 从下一个位置开始选已选数量1总和加上 a[i] } }详细分析这是代码的灵魂完美实现了组合枚举。递归终止条件当cur k时说明已经凑齐了 kk 个数此时直接调用is_prime(sum)进行判定如果为真则全局答案ans加 1。避免重复的核心for循环的起始值是start而递归调用时传入的是i1。这意味着如果当前选择了第i个数下一层递归只能从i1及之后的数中选择。这保证了选出的数在原数组中的下标是严格递增的从而避免了3719和7319这种重复计算。可行性剪枝循环的终止条件i n-(k-cur)1是一个经典的组合数学优化。它的意思是当前还需要选k-cur个数如果从当前位置i往后数剩下的数字个数已经不够填满这k-cur个位置了那么继续枚举i及其后面的数就没有意义了直接跳出循环。4. 主函数输入处理与启动搜索int main(){ ios::sync_with_stdio(false); cin.tie(0); cinnk; // 读入 n 和 k for(int i1;in;i) cina[i]; // 读入 n 个整数 dfs(1,0,0); // 从第 1 个数开始选当前选了 0 个当前总和为 0 coutans; // 输出和为素数的组合种类数 return 0; }详细分析主函数负责数据的读入和算法的启动。dfs(1,0,0)表示从数组的第 1 个位置开始尝试选择当前已经选了 0 个数当前的累加和为 0。核心逻辑总结表代码模块核心变量/操作精炼作用解决的痛点素数判定is_prime(int x)试除法判断一个数是否为素数准确判定组合的和是否符合题目要求i*ix保证了效率递归终止if(curk)判断是否已经选够了 k 个数到达搜索树的叶子节点进行结果统计避免重复dfs(i1, ...)下一层递归只能从当前数的下一个位置开始选保证选出的组合下标严格递增避免了排列带来的重复计算可行性剪枝i n-(k-cur)1限制当前层枚举的上界当剩余数字不足以凑齐 k 个数时提前终止大幅减少无效搜索状态传递suma[i]将当前选择的数累加到总和中在递归过程中动态维护当前组合的总和避免了在叶子节点重新遍历求和全局计数ans累加满足条件的组合数记录最终的答案

相关新闻

别再背 slice 扩容公式了:1.18 真正改掉了什么

别再背 slice 扩容公式了:1.18 真正改掉了什么

2048 → 1280。 你没看错。在 Go 1.17 里,我把一个 cap1023 的 []byte append 一次,新 cap 是 2048;把同样的代码换成 cap1024,append 一次,新 cap 反而变成 1280。 old cap 只增加了 1,new cap 直接少了…

2026/7/10 22:43:38阅读更多 →
机器人领域“AGV调度优化”高价值专利案例:一种智能车间AGV调度优化方法

机器人领域“AGV调度优化”高价值专利案例:一种智能车间AGV调度优化方法

课题来源:某智能制造装备企业横向研发委托项目案例定位:面向智能车间多AGV路径冲突、传统静态调度响应滞后、多工序任务耦合下转运效率低、约束优化求解实时性差等痛点,开展融合空间路径映射、二次规划约束优化、递归神经动力学实时求解的车间…

2026/7/10 22:43:38阅读更多 →
2026无人机超高清地图推荐

2026无人机超高清地图推荐

各位飞手兄弟们,2026年又快过半了,咱们手里的植保机固件不知道更新了多少回,但你是不是还在用那种糊成一团的卫星地图?规划地块时,田埂看不清、电线杆靠猜、边界画得手发抖?别让烂地图拖了无人机的后腿&…

2026/7/10 22:43:38阅读更多 →
witty-opencode故障排查手册:从安装失败到配置冲突的完整解决指南

witty-opencode故障排查手册:从安装失败到配置冲突的完整解决指南

witty-opencode故障排查手册:从安装失败到配置冲突的完整解决指南 【免费下载链接】witty-opencode AI agent client built on top of OpenCode, including the TUI frontend, agent backend, and SDK. 项目地址: https://gitcode.com/openeuler/witty-opencode …

2026/7/10 23:43:42阅读更多 →
openEuler-bootstrap完全配置指南:从环境搭建到成功构建

openEuler-bootstrap完全配置指南:从环境搭建到成功构建

openEuler-bootstrap完全配置指南:从环境搭建到成功构建 【免费下载链接】openEuler-bootstrap Build new openEuler architecture bootstrap rpms from scratch 项目地址: https://gitcode.com/openeuler/openEuler-bootstrap 前往项目官网免费下载&#xf…

2026/7/10 23:43:42阅读更多 →
Nginx服务部署

Nginx服务部署

基础部署:单实例Nginx快速启动部署前环境准备确保Docker环境就绪:docker --version验证安装,docker-compose --version检查编排工具。端口规划需避开系统占用,HTTP默认80端口,HTTPS默认443端口。如需SSL访问&#xff0…

2026/7/10 23:43:42阅读更多 →
openeuler/security-baseline路线图:未来功能增强与框架优化展望

openeuler/security-baseline路线图:未来功能增强与框架优化展望

openeuler/security-baseline路线图:未来功能增强与框架优化展望 【免费下载链接】security-baseline Hardening the system security to ensure that the system complies with various security hardening baselines to improve system security. Supports system…

2026/7/10 23:43:42阅读更多 →
编译原理:有限自动机

编译原理:有限自动机

📌目录 ⚖️ 有限自动机:词法识别的计算模型 🎯 一、有限自动机概述 (一)有限自动机的概念 (二)有限自动机的形式化定义 📦 二、确定性有限自动机(DFA) (一)DFA的定义 (二)DFA的运行 (三)DFA的表示 🌐 三、非确定性有限自动机(NFA) (一)NFA的定义 (二…

2026/7/10 23:43:42阅读更多 →
PilotGo-plugin-ELK与PilotGo平台集成:打造一体化运维管理

PilotGo-plugin-ELK与PilotGo平台集成:打造一体化运维管理

PilotGo-plugin-ELK与PilotGo平台集成:打造一体化运维管理 【免费下载链接】PilotGo-plugin-ELK ELK plugin for PilotGo. 项目地址: https://gitcode.com/openeuler/PilotGo-plugin-ELK 前往项目官网免费下载:https://ar.openeuler.org/ar/ Pil…

2026/7/10 23:38:42阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/10 12:10:00阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/10 12:29:21阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/10 4:59:05阅读更多 →
浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比

浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比

浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比当你在浏览器地址栏敲入一个网址时,背后可能隐藏着一场关于"要不要重新下载资源"的精密博弈。这场博弈的裁判是HTTP缓存机制,而304状态码则是这场博弈…

2026/7/10 0:00:01阅读更多 →
RoboWits:面向创造性问题求解的双臂机器人认知推理基准

RoboWits:面向创造性问题求解的双臂机器人认知推理基准

1. 项目概述:这不是又一个机器人抓取数据集,而是一次对“思考力”的压力测试 RoboWits——这个名字里藏着两个关键信号:“Robo”直指物理世界中的具身智能体,“Wits”则毫不掩饰地指向人类最核心的认知能力:机敏、判断…

2026/7/10 0:00:01阅读更多 →
5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能

5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能

5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windows…

2026/7/10 0:00:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/10 13:39:09阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/10 22:20:33阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/10 17:29:22阅读更多 →