news 2026/4/30 13:58:35

如何用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/4/30 17:00:24

41、系统编程知识与技巧深度解析

系统编程知识与技巧深度解析 在系统编程领域,掌握各类关键技术和工具是提升编程能力的关键。本文将深入探讨系统编程中的多个重要方面,包括GCC扩展、文件操作、内存管理、线程与进程管理以及时间处理等内容。 1. GCC扩展特性 GCC编译器提供了一些实用的扩展特性,能增强代…

作者头像 李华
网站建设 2026/4/29 8:31:42

NocoDB容器化实战:从零到一搭建可视化数据库管理平台

NocoDB容器化实战&#xff1a;从零到一搭建可视化数据库管理平台 【免费下载链接】nocodb nocodb/nocodb: 是一个基于 node.js 和 SQLite 数据库的开源 NoSQL 数据库&#xff0c;它提供了可视化的 Web 界面用于管理和操作数据库。适合用于构建简单的 NoSQL 数据库&#xff0c;特…

作者头像 李华
网站建设 2026/4/19 2:39:11

老旧Mac升级革命:OCLP-Mod让你的设备重获新生体验

老旧Mac升级革命&#xff1a;OCLP-Mod让你的设备重获新生体验 【免费下载链接】OCLP-Mod A mod version for OCLP,with more interesting features. 项目地址: https://gitcode.com/gh_mirrors/oc/OCLP-Mod 在苹果生态系统中&#xff0c;硬件淘汰周期正不断缩短&#xf…

作者头像 李华
网站建设 2026/4/28 6:02:07

虚拟桌宠模拟器的单元测试策略:从零构建可靠测试体系

虚拟桌宠模拟器的单元测试策略&#xff1a;从零构建可靠测试体系 【免费下载链接】VPet 虚拟桌宠模拟器 一个开源的桌宠软件, 可以内置到任何WPF应用程序 项目地址: https://gitcode.com/GitHub_Trending/vp/VPet 为什么你的桌宠项目需要重构测试架构&#xff1f; 你是…

作者头像 李华
网站建设 2026/4/18 10:35:00

PortProxyGUI:Windows端口转发的终极图形化解决方案

PortProxyGUI&#xff1a;Windows端口转发的终极图形化解决方案 【免费下载链接】PortProxyGUI A manager of netsh interface portproxy which is to evaluate TCP/IP port redirect on windows. 项目地址: https://gitcode.com/gh_mirrors/po/PortProxyGUI PortProxyG…

作者头像 李华
网站建设 2026/4/24 12:18:04

如何3步搞定Netflix 4K画质优化:告别模糊画面的终极方案

你是否曾经在Netflix上观看4K影片时&#xff0c;明明订阅了最高套餐&#xff0c;却总觉得画质不够清晰锐利&#xff1f;这背后隐藏着流媒体平台的技术限制和浏览器默认设置的问题。今天分享的这款Edge插件&#xff0c;将彻底解决你的困扰&#xff0c;让你的观影体验达到影院级水…

作者头像 李华