数字重构
数字重构
给定两个正整数 和 ,均不含前导 。
现在,请你对 进行重构,重新排列其各位数字顺序,得到一个不含前导 的新正整数。
要求新正整数在不超过 的前提下,尽可能大。
输出新正整数。
注意,我们允许新正整数等于 ,即保持原样不变。
输入格式
第一行包含一个正整数 。
第二行包含一个正整数 。
两个输入数字均不含前导 。
输出格式
一个不含前导 的正整数,表示答案。
数据保证一定有解。
数据范围
前 个测试点满足 。
所有测试点满足 。
输入样例1:
123 222
输出样例1:
213
输出样例2:
3921 10000
输出样例2:
9321
输入样例3:
4940 5000
输出样例3:
4940
解题思路
这题其实很简单,但是在比赛的时候没想出来,我太弱了...qwq...
这是一个很经典的贪心问题。求一个字典序最小的序列,或者是求一个最小的数,我们的贪心思路是,从最高位往低位去找,在满足条件的情况下从最大的数往小的数枚举。
比如这题,我们从最高位开始找,从开始枚举,看看是否满足条件,如果不满足条件就看看,如果不满足条件就再看......,以此类推。
那么我们如何判断每一位选的数是否满足条件呢?首先这个数是可以选到的,同时选了这个数后,前面的位已经固定,后面的位应该存在一种摆法,使得。要判断,可以判断后面的最小摆法(后面的位按数字递增摆)小于等于,即。
AC代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 7 int cnt[10]; 8 9 string get_min(int n) { 10 string ret = to_string(n); 11 cnt[n]--; 12 13 for (int i = 0; i <= 9; i++) { 14 for (int j = 0; j < cnt[i]; j++) { 15 ret += to_string(i); 16 } 17 } 18 19 cnt[n]++; 20 21 return ret; 22 } 23 24 int main() { 25 string a, b; 26 cin >> a >> b; 27 28 // 把a的每位数字取出来 29 for (int i = 0; i < a.size(); i++) { 30 cnt[a[i] - '0']++; 31 } 32 33 // 如果a的位数小于b,a能取到最大的数就是按递减的顺序排 34 if (a.size() < b.size()) { 35 sort(a.begin(), a.end(), greater<char>()); 36 cout << a; 37 } 38 else { 39 string ret; 40 for (int i = 0; i < a.size(); i++) { // 从最高位开始找 41 int j = 9; // 每一位从9开始枚举 42 // 找到一个数,这个数要存在,同时后面的最小摆法要小于b 43 while (cnt[j] == 0 || ret + get_min(j) > b) { 44 j--; 45 } 46 ret += to_string(j); 47 cnt[j]--; 48 } 49 cout << ret; 50 } 51 52 53 return 0; 54 }
参考资料
AcWing 4307. 数字重构(AcWing杯 - 周赛):https://www.acwing.com/video/3719/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/15941802.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效