Nearest Beautiful Number (easy version)

题目

Nearest Beautiful Number (easy version)


问题描述

给定数据 n ( 1 ≤ n ≤ 1 0 9 ) n(1\leq n\leq10^9) n(1n109) k ( k ≤ 2 ) k(k\leq2) k(k2)
x x x由不超过 k k k种数字所组成,输出满足 x ≥ n x\geq n xn中最接近 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 i1位数据大于等于 n n n的前 i − 1 i-1 i1位数据,

若第 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值