题目
Nearest Beautiful Number (easy version)
问题描述
给定数据 n ( 1 ≤ n ≤ 1 0 9 ) n(1\leq n\leq10^9) n(1≤n≤109)跟 k ( k ≤ 2 ) k(k\leq2) k(k≤2)
x x x由不超过 k k k种数字所组成,输出满足 x ≥ n x\geq n x≥n中最接近 n n n的 x x x。
例: n = 177890 , k = 2 n=177890,k=2 n=177890,k=2
输出 x = 181111 x=181111 x=181111
分析
思路一(先枚举再二分)
由于数据的范围,所以有一个取巧的办法,先在set1里面存入k为1的数据,也就9个;再在set2里面存入满足k为2的数据(由一个数字或两个数字组成),通过循环可以依次枚举出来。
最后输入n跟k后,只需要在对应的集合里面用函数二分查找出大于等于n的第一个数,就是满足条件的x。
思路二(循环模拟)
当k等于1时,只需要从大到小枚举字符串,输出第一个大于等于n的字符串,转为字符串后字符串比较的规则与数的大小比较规则是一致的;
而且有个规律:从n中取出前t位,与x中的前t位仍然满足条件。
当k等于2时,由于数据不大,此时可以通过模拟来找出第一个符合条件的x:
给定 a a a跟 b b b,满足 a < b a<b a<b,先假设可以通过 a , b a,b a,b构建出满足条件的x,而且为了找到第一个, a , b a,b a,b的枚举是从小到大枚举的,所以接下来的目标变为了找到第一个满足 x > = n x>=n x>=n且只需要用两种数字表示的 x x x。
for(char a = '0'; a <= '8'; a++)for (char b = a + 1; b <= '9'; b++){
//......}
确定了 a , b a,b a,b之后,要看是否可以由 a , b a,b a,b构建出满足条件的x,接下来的循环是由n的第一位开始,直至结束。
处理第 i i i位的数据时,我们保证由 a a a, b b b构建的 x x x的前 i ? 1 i-1 i?1位数据大于等于 n n n的前 i ? 1 i-1 i?1位数据,
若第 i i i位大于 a a a跟 b b b,说明这一搭配是不合理的,退出,测试下一组 a , b a,b a,b;
若第 i i i位小于等于 b b b,说明这一位可以使用 a , b a,b a,b来替代,由于 a a a更小,为了满足题目要求最接近的最小值,我们优先测试 a a a,若大于 a a a,再选择 b b b,此时由 a a a, b b b构建的 x x x的前 i i i位数据大于等于 n n n的前 i i i位数据, 再测试第 i + 1 i+1 i+1位
当我们找到了一组 a , b a,b a,b可以完全表示出每一位都满足条件的 x x x时,这个 x x x就是我们的答案,可以返回结果了。
代码
#include <bits/stdc++.h>using namespace std;string solve1(string n)
{
string res(n.length(), '9');for (char c = '8'; c >= '0'; c--){
string t(n.length(), c);if (t >= n)res = t;}return res;
}string solve2(string n)
{
string res(n.length(), '9');for(char a = '0'; a <= '8'; a++)for (char b = a; b <= '9'; b++){
bool n_ok = true;for (int i = 0; i < n.length(); i++){
if (n[i] < b){
string t = n;if (t[i] < a) t[i] = a;else t[i] = b;for (int j = i + 1; j < n.length(); j++)t[j] = a;if (res > t)res = t;}if(n[i] != a && n[i] != b){
n_ok = false;break;}}if (n_ok) return n;}return res;
}string solve()
{
string n;int k;cin >> n >> k;if (k == 1) return solve1(n);else return solve2(n);
}int main()
{
int t;cin >> t;while (t--)cout << solve() << '\n';return 0;
}