CF#739-F2 Nearest Beautiful Number (hard version)

Nearest Beautiful Number (hard version)

全局链接: Codeforces Round #739 (Div. 3)

题目大意:

​ 用不大于k种数字,构造出比n大的最小值。

大佬的思路:

我太菜了做不来,学习了大佬的思路,他的代码真的很好看===>大佬传送门

因为要是最小的数,所以从低位到高位遍历,每个数都可能可以变得比他大,变了之后要数一下该位置前面(包括自己)的数字中有多少重复数字。若刚刚好是k,那么就要将其后(不包括自己)的所有书变成最小的数;若不到k,那就全部用0。贪的很漂亮啊!!!

#include<bits/stdc++.h>
using namespace std;
string n;
int k;

int cal(string ss){
	set<char> s;//set算不同元素的数量 
	for(auto c: ss)s.insert(c);
	return s.size();
}

string solve(){
	cin>>n>>k;
	if(cal(n) <= k)return n;//若n的数字种类小于kn就是符合条件的k-beautiful数
	 
	int len = n.length();
	for(int i = len - 1;i >= 0; i--){//从后往前修改修改的位数越少数字就越小 
		string tmp = n;//所有的操作都在tmp上做
		//修改数字实质上只需要修改一位,将那一位改掉大之后,因为要尽可能小,其后面所有的数字 都改成0或者最小数 
		for(char j = n[i] + 1;j <= '9'; j++){//j是比现在位大的一位数。
			set<char>ck;
			tmp[i] = j;
			for(int k = 0;k <= i; k++)ck.insert(tmp[k]);
			if(cal(tmp.substr(0,i + 1)) > k)continue;//前面的数字种类多于k就要到下一个j去判断
			
			char p = ( cal(tmp.substr(0,i + 1)) == k )? *ck.begin() : '0'; //.begin返回的是地址,要*变成值 
			for(int k = i + 1; k < len ; k++)tmp[k] = p;
			
			if(stoi(tmp) >= stoi(n))//string to int 
				return tmp;//经过以上除此if的操作后,若tmp是不小于n的那就是最小的满足条件的数字 
		}
	}
}

int main(){
	int T;cin>>T;
	while(T--)
		cout<<solve()<<"\n";
	return 0;
}

笔记:

1、cal函数 用set算不重复的元素数量

2、用 for(auto c : ss) 遍历容器

3、stoi() string直接转int的函数

4、从后到前考虑使得答案最小

posted @ 2021-08-23 22:13  tyrii  阅读(50)  评论(0)    收藏  举报