蓝桥杯备赛: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<n,每个整数 < 5 × 10 6 < 5 \times 10^6 <5×106。

2. 核心代码 (C++ AC版本)

c++ 复制代码
#include <bits/stdc++.h>
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 ),是应对高频调用的标准写法。
相关推荐
程与留6 小时前
14_Qt 样式表(QSS)入门(语法、选择器、美化实战)
c++·qt
欧特克_Glodon14 小时前
OpenCV计算机视觉开发入门与实践<二十七>:图像分割概述
c++·人工智能·opencv·计算机视觉
蒸蒸yyyyzwd14 小时前
cpp 选手秋招学习笔记 day21
c++·面试·八股
「QT(C++)开发工程师」1 天前
C++ auto 用法详解
开发语言·c++
OPEN-F1 天前
C++STL教程:容器适配器与实用工具
开发语言·c++
OPEN-F1 天前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++
有点。1 天前
C++二叉搜索树进阶
开发语言·c++
HugoStudio_SWAN1 天前
【擦除重绘】C++ 控制台动画:弹跳 Logo DVD 屏保效果
开发语言·c++·学习·程序人生
kyle~1 天前
C++_STL---迭代器失效
开发语言·c++
wuminyu1 天前
深入剖析 Panama Off-heap 的性能损耗与开销
java·linux·c语言·jvm·c++