蓝桥杯备赛:Day5-P1036 选数

📚 算法笔记:P1036 [NOIP 2002 普及组] 选数

1. 题目描述

P1036 [NOIP 2002 普及组\] 选数 - 洛谷](https://www.luogu.com.cn/problem/P1036) 从 n n n 个整数中任选 k k k 个数相加,统计有多少种选法的**和** 为**质数**。 * 数据范围: n ≤ 20 , k \< n n \\le 20, k \< n n≤20,k\ using namespace std; typedef long long ll; ll a[25]; // 存储输入的 n 个数 int N, K; ll ans = 0; // 计数器:符合条件的质数和个数 // 质数判定:O(sqrt(sum)) bool is_prime(int n) { if (n < 2) return false; for (int i = 2; i * i <= n; i++) { if (n % i == 0) return false; } return true; } // DFS 组合模型 // position: 当前选到了第几个数 // sum: 当前已选数字的累加和 // start: 搜索起点,保证下标单调递增 void dfs(int position, ll sum, int start) { // 1. 递归出口:选够了 K 个数 if(position > K) { if(is_prime(sum)) ans++; return; } // 2. 组合模型核心:从 start 开始往后选,不回头 for(int i = start; i <= N; i++) { // 隐式回溯:sum + a[i] 作为参数传递,无需手动撤销 dfs(position + 1, sum + a[i], i + 1); } } void solve() { if(!(cin >> N >> K)) return; for (int i = 1; i <= N; i++) cin >> a[i]; ans = 0; dfs(1, 0, 1); cout << ans << endl; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int _ = 1; while(_--) solve(); return 0; } ``` *** ** * ** *** #### 3. 核心考点与注意事项 * **组合模型 (Combination)** :与全排列不同,组合不计较顺序。通过引入 `start` 参数,强制让选取的下标**单调递增** ( i → i + 1 i \\rightarrow i+1 i→i+1),从而物理隔绝了重复排列(如选了 1 , 2 1,2 1,2 就不会再选 2 , 1 2,1 2,1)。 * **隐式回溯** :在 `dfs(position + 1, sum + a[i], i + 1)` 中,`sum + a[i]` 的结果直接传给下一层。当递归返回时,本层的 `sum` 值并没有改变,因此**不需要** 像 `used` 数组那样手动执行 `sum -= a[i]`。 * **质数优化** :使用 `i * i <= n` 进行判定,时间复杂度为 O ( N ) O(\\sqrt{N}) O(N ),是应对高频调用的标准写法。

相关推荐
万法若空3 小时前
C++ <memory> 库全方位详解
开发语言·c++
代码中介商3 小时前
C++ 类型转换深度解析:static_cast、dynamic_cast、const_cast、reinterpret_cast
开发语言·c++
青小莫3 小时前
C++之string(OJ练习)
开发语言·c++·stl
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 199. 二叉树的右视图 | C++ DFS 逆序遍历
c++·leetcode·深度优先
-Marks-3 小时前
【C++编程】STL简介 --- (是什么 | 版本发展历程 | 六大组件 | 重要性缺陷以及如何学习)
开发语言·c++·学习·stl·stl版本
CoderCodingNo4 小时前
【信奥业余科普】C++ 的奇妙之旅 | 12:程序的交互与加工——数据的输入与算术运算
开发语言·c++
yx868xy4 小时前
Cuda加速直线拟合
c++·cuda
蜗牛在听雨5 小时前
基于 C++ 的 UG/NX 二次开发环境配置
c++·二次开发·ug
SimpleLearingAI5 小时前
C++虚函数详解
开发语言·c++