news 2026/5/12 5:49:34

如何用C++解决“选数求和“问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用C++解决“选数求和“问题

浅浅氵一篇特地写篇笔记

假设手头有 n 个数字,需要从中选出 k 个不同的数字相加。问题是:有多少种选法,能让这 k 个数字的和是质数?

举个简单的例子:
有数字:3, 7, 12, 19
要从中选 3 个数字相加
那么所有可能的组合是:
3+7+12=22(不是质数)
3+7+19=29(是质数!)
3+12+19=34(不是质数)
7+12+19=38(不是质数)

所以答案是:只有 1 种选法能得到质数和。

核心思路分析

这个问题看似简单,但涉及到几个关键点:

1. 组合问题 vs 排列问题

这是最开始容易混淆的地方:

  • 组合:{3,7,12} 和 {7,3,12} 是同一个组合,顺序不重要

  • 排列:{3,7,12} 和 {7,3,12} 是不同的排列,顺序很重要

这个问题显然是组合问题,所以需要避免重复计数。

2. 质数判断

质数是只能被1和自身整除的大于1的自然数。比如:2, 3, 5, 7, 11……

判断一个数是不是质数,最直接的方法就是检查它能不能被2到n-1之间的数整除。但是这样太慢了!有个小技巧:只需要检查到 √n 就可以了

为什么呢?因为如果一个数 n 有大于√n的因子,那它必然有小于√n的对应因子。

代码实现过程

我先把完整的代码展示一下,然后详细解释:

#include<iostream> using namespace std; int n, k, a[100010], b[100010], cnt = 0; bool judge(int y)//判断质数 { if (y < 2) return 0; for (int i = 2; i * i <= y; i++) { if (y % i == 0)return 0; } return 1; } void dfs(int x) { if (x == k + 1) { int sum=0; for (int i = 1; i <= k; i++) { sum += b[a[i]]; } if (judge(sum)) cnt++; return; } for (int i = a[x - 1] + 1; i <= n; i++) { a[x] = i; dfs(x + 1); } } int main() { cin >> n >> k; for (int i = 1; i <= n;i++) { cin >> b[i]; } dfs(1); cout << cnt; return 0; }

代码逐行解析

第一部分:头文件和变量声明

#include<iostream> using namespace std; int n, k, a[100010], b[100010], cnt = 0;
  • #include<iostream>:引入输入输出流库,相当于拿到控制台的"遥控器"

  • using namespace std;:打开标准命名空间,这样写cout时就不用写成std::cout

  • 变量声明:

    • n:总共有多少个数字

    • k:要选几个数字

    • a[100010]:记录选择了哪些数字的位置(索引)

    • b[100010]:存储实际的数字

    • cnt:计数器,记录符合条件的方案数,初始化为0

第二部分:质数判断函数

bool judge(int y)//判断质数 { if (y < 2) return 0; // 小于2肯定不是质数 for (int i = 2; i * i <= y; i++) // 只检查到sqrt(y) { if (y % i == 0)return 0; // 如果能整除,不是质数 } return 1; // 通过了所有检查,是质数 }

这个函数很关键!检查范围是i * i <= y而不是i <= y,这就是刚才说的优化技巧。

第三部分:深度优先搜索(DFS)

void dfs(int x) { if (x == k + 1) // 已经选了k个数字 { int sum=0; for (int i = 1; i <= k; i++) // 计算选出的k个数字的和 { sum += b[a[i]]; // a[i]记录的是位置,b[a[i]]才是实际数字 } if (judge(sum)) cnt++; // 如果是质数,计数器加1 return; } for (int i = a[x - 1] + 1; i <= n; i++) // 关键!避免重复 { a[x] = i; // 记录选择第i个数字 dfs(x + 1); // 继续选择下一个数字 } }

这是算法的核心!用深度优先搜索来生成所有组合。

解释一下关键点:

  • x参数表示当前正在选第几个数字

  • x == k + 1时,说明已经选了k个数字,可以计算和并判断了

  • 循环中的i = a[x - 1] + 1确保了每次选择的位置都比上一次大,这样就避免了重复组合

比如:选择了位置2的数字后,下一次就从位置3开始选,不会回头选位置1,这样就不会产生{1,2,3}和{2,1,3}这样的重复。

第四部分:主函数

int main() { cin >> n >> k; // 读取n和k for (int i = 1; i <= n;i++) // 读取n个数字 { cin >> b[i]; // 存储到b数组中 } dfs(1); // 从选第1个数字开始 cout << cnt; // 输出结果 return 0; }

我踩过的坑

坑1:数组索引的选择

一开始还挺纠结:数组索引到底该从0开始还是从1开始?最后我选择了从1开始,因为这样更直观:

  • b[1]存储第1个数字

  • b[2]存储第2个数字

  • 以此类推……

但要注意:循环条件也要相应调整,比如for (int i = 1; i <= n; i++)而不是for (int i = 0; i < n; i++)

坑2:全局变量的初始化

在代码中,数组a[100010]是全局变量。这里有个小知识点:全局变量会自动初始化为0

所以当我第一次调用dfs(1)时:

for (int i = a[x - 1] + 1; i <= n; i++) // 第一次:i = a[0] + 1 = 0 + 1 = 1

这样就正确地从第1个位置开始选择了。

如果a是局部变量,就需要手动初始化为0了。

坑3:和的计算时机

我最初犯过一个错误:在每次递归时都计算部分和。但其实等到选满k个数字后再一次性计算更简单。

算法复杂度分析

这个算法的时间复杂度主要取决于:

  1. 组合数:C(n,k) 种选择方案

  2. 每种方案需要O(√sum)的时间判断质数

对于n≤20的情况,完全在可接受范围内。

总结

  1. DFS是解决组合问题的利器,通过维护起始位置可以避免重复

  2. 质数判断有优化技巧,只需检查到√n

  3. 全局变量会自动初始化,这个细节很重要

  4. 代码调试要耐心,有时候小错误会导致大问题

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 13:24:27

AI语音合成推理优化终极指南:35倍性能提升的完整教程

AI语音合成推理优化终极指南&#xff1a;35倍性能提升的完整教程 【免费下载链接】GPT-SoVITS 项目地址: https://gitcode.com/GitHub_Trending/gp/GPT-SoVITS 在当今AI语音合成技术快速发展的时代&#xff0c;推理速度已成为影响用户体验的关键因素。本文将深入解析如…

作者头像 李华
网站建设 2026/5/12 12:14:41

跨语言阅读革命:kiss-translator智能翻译插件深度解析

跨语言阅读革命&#xff1a;kiss-translator智能翻译插件深度解析 【免费下载链接】kiss-translator A simple, open source bilingual translation extension & Greasemonkey script (一个简约、开源的 双语对照翻译扩展 & 油猴脚本) 项目地址: https://gitcode.com…

作者头像 李华
网站建设 2026/5/9 12:30:52

基于MATLAB实现的鲁棒性音频数字水印系统

基于 MATLAB 实现的 鲁棒性音频数字水印系统 &#xff0c;结合 DWT-DCT联合变换 和 量化索引调制&#xff08;QIM&#xff09;&#xff0c;支持二值水印嵌入与提取&#xff0c;并通过仿真实验验证其抗攻击能力。一、系统架构设计二、核心代码 1. 水印预处理&#xff08;二值化与…

作者头像 李华
网站建设 2026/5/11 10:07:17

LoRA技术中文网络小说创作终极指南:从入门到精通

LoRA技术中文网络小说创作终极指南&#xff1a;从入门到精通 【免费下载链接】Qwen3-4B Qwen3-4B&#xff0c;新一代大型语言模型&#xff0c;集稠密和混合专家&#xff08;MoE&#xff09;模型于一体。突破性提升推理、指令遵循、代理能力及多语言支持&#xff0c;自如切换思维…

作者头像 李华
网站建设 2026/5/9 12:51:39

Material Kit轮播图实战指南:打造动态内容展示的艺术

Material Kit轮播图实战指南&#xff1a;打造动态内容展示的艺术 【免费下载链接】material-kit Free and Open Source UI Kit for Bootstrap 5, React, Vue.js, React Native and Sketch based on Googles Material Design 项目地址: https://gitcode.com/gh_mirrors/ma/ma…

作者头像 李华
网站建设 2026/5/10 9:15:48

2025智能垃圾分类数据集:从数据标注到模型部署的完整指南

2025智能垃圾分类数据集&#xff1a;从数据标注到模型部署的完整指南 【免费下载链接】垃圾分类数据集 项目地址: https://ai.gitcode.com/ai53_19/garbage_datasets 你可能在构建垃圾分类模型时遇到这样的问题&#xff1a;标注数据格式不统一导致训练失败&#xff0c;…

作者头像 李华