蓝桥杯备赛: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 ),是应对高频调用的标准写法。

相关推荐
mmz12072 小时前
深度优先搜索DFS(c++)
c++·算法·深度优先
憧憬从前4 小时前
算法学习记录DAY1
c++·学习
A.A呐4 小时前
【C++第二十四章】异常
开发语言·c++
xiaoye-duck4 小时前
《算法题讲解指南:动态规划算法--子序列问题》--29.最长递增子序列的个数,30.最长数对链,31.最长定差子序列
c++·算法·动态规划
森G4 小时前
39、拓展知识---------事件系统
c++·qt
啊我不会诶4 小时前
十三届蓝桥杯省赛A组 选数异或
职场和发展·蓝桥杯
tankeven4 小时前
HJ164 太阳系DISCO
c++·算法
君鼎5 小时前
C++17 新特性全面总结
c++
不爱吃炸鸡柳5 小时前
[特殊字符]C/C++内存管理深度解剖:从内存布局到new/delete底层,吃透面试必考核心
c语言·c++·面试