csp信奥赛C++高频考点专项训练之贪心算法 --【删数问题】:删数问题2

csp信奥赛C++高频考点专项训练之贪心算法 --【删数问题】:删数问题2

题目描述

一个集合有如下元素: 1 1 1 是集合元素;若 P P P 是集合的元素,则 2 × P + 1 2\times P+1 2×P+1, 4 × P + 5 4\times P+5 4×P+5 也是集合的元素。

取出此集合中最小的 k k k 个元素,按从小到大的顺序组合成一个多位数,现要求从中删除 m m m 个数位上的数字,使得剩下的数字最大,编程输出删除前和删除后的多位数字。

注:不存在所有数被删除的情况。

输入格式

只有一行两个整数,分别代表 k k k 和 m m m。

输出格式

输出为两行两个整数,第一行为删除前的数字,第二行为删除后的数字。

输入输出样例 1
输入 1
复制代码
5 4
输出 1
复制代码
137915
95
数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 1 ≤ k , m ≤ 300 1\le k,m\le300 1≤k,m≤300。
  • 对于 100 % 100\% 100% 的数据,保证 1 ≤ k , m ≤ 3 × 10 4 1\le k,m\le3\times10^4 1≤k,m≤3×104。

思路分析

  1. 生成最小的 k 个集合元素

    集合定义:1 在集合中;若 P 在集合中,则 2P+1 和 4P+5 也在集合中。

    要得到最小的 k 个元素,可以使用最小堆(优先队列)进行 BFS。

    • 初始将 1 入堆,并用哈希集合记录已生成的数,避免重复。
    • 每次弹出堆顶(当前最小值),将其加入结果数组,然后生成两个新数,若未出现过则入堆。
    • 重复 k 次即得到有序的前 k 个元素。
  2. 拼接成多位数

    将每个元素转换为字符串,按顺序拼接得到长字符串 s。

  3. 删除 m 个数字使剩下的数字最大

    经典贪心问题:使用单调栈。

    • 遍历 s 的每个字符 c,当栈非空且栈顶字符 < c 且还有删除次数时,弹出栈顶(删除该数字),删除次数减 1。
    • 将 c 压入栈。
    • 遍历结束后若还有删除次数,从栈末尾删除相应个数。
      最终栈内字符即为所求的最大数字串。
  4. 输出

    第一行输出删除前的多位数 s,第二行输出删除后的多位数。

代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    int k, m;
    cin >> k >> m;
    
    // 最小堆生成最小的k个元素
    priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆
    unordered_set<long long> vis; // 去重
    vector<long long> a; // 存放取出的元素
    
    pq.push(1);
    vis.insert(1);
    while (a.size() < k) {
        long long x = pq.top(); pq.pop();
        a.push_back(x);
        long long y1 = 2 * x + 1;
        long long y2 = 4 * x + 5;
        if (!vis.count(y1)) {
            pq.push(y1);
            vis.insert(y1);
        }
        if (!vis.count(y2)) {
            pq.push(y2);
            vis.insert(y2);
        }
    }
    
    // 拼接成多位数
    string s;
    for (long long v : a) {
        s += to_string(v);
    }
    
    // 贪心删除m个数字使剩余最大
    string st; // 栈
    int d = m;
    for (char c : s) {
        while (d > 0 && !st.empty() && st.back() < c) {
            st.pop_back();
            d--;
        }
        st.push_back(c);
    }
    if (d > 0) st.erase(st.end() - d, st.end());
    
    // 输出
    cout << s << "\n" << st << "\n";
    
    return 0;
}

功能分析

  • 生成模块:使用最小堆和哈希集合,时间复杂度 O(k log k),空间复杂度 O(k),生成前 k 个最小元素并保持有序。
  • 拼接模块 :遍历元素数组,调用 to_string 并连接,总长度 S 约为 k 乘以平均位数(对于 k=3e4,S 约 2e5),时间 O(S)。
  • 删除模块:单遍扫描字符串,利用栈维护单调递减趋势,时间复杂度 O(S),空间复杂度 O(S)。
  • 输出模块:直接输出两个字符串。

正确性:贪心删除策略保证了每次删除使剩余数字尽可能大的局部最优,全局最优由单调栈性质保证。

各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
hanbr2 小时前
Leetcode刷题总结(1)
算法·leetcode·职场和发展
B站_计算机毕业设计之家2 小时前
计算机毕业设计:Python股票投资辅助决策系统 django框架 request爬虫 协同过滤算法 数据分析 可视化 大数据 大模型(建议收藏)✅
爬虫·python·深度学习·算法·django·flask·课程设计
_日拱一卒2 小时前
LeetCode:随机链表的复制
算法·leetcode·链表
SWAGGY..2 小时前
【C++初阶】:(10)vector的使用及模拟实现
开发语言·c++
菜菜的顾清寒2 小时前
力扣笔记自用
笔记·算法·leetcode
SariHcr1232 小时前
Openarm机器人双臂模型仿真从零部署
c++·人工智能·python·机器人·bash·openarm
故事还在继续吗2 小时前
C++11关键特性
开发语言·c++·算法
格林威2 小时前
面阵相机 vs 线阵相机:堡盟与Basler选型差异全解析 +C++ 实战演示
开发语言·c++·人工智能·数码相机·计算机视觉·视觉检测·工业相机
zzzsde2 小时前
【Linux】线程概念与控制(2)线程控制与核心概念
linux·运维·服务器·开发语言·算法