现已加入每日暴力&构造 练习
这是day1

题意:给你\(n\)\(k\),找到最小的\(\ge n\)且包含不超过\(k\)个字符的最小数字。

sol:找到\(n\)​的最长的包含\(k\)​个字符的前缀,如果这个前缀合起来就是\(n\),直接输出\(n\)​即可。不然可以枚举合法前缀,将其加上1~9,使得非前缀部分全部变为前缀中最小的那个数字。

时间复杂度\(O(T\log^3 n)\)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 20;
#define ll long long
ll top, stk[maxn], n, k, T;
bool vis[maxn];
bool check(int x) {
	memset(vis, 0, sizeof(vis));
	int cnt = 0;
	while (x) {
		if (!vis[x % 10]) {
			vis[x % 10] = 1;
			cnt++;
		}
		x /= 10;
	}
	return cnt <= k;
}
ll ans;
int main() {
	scanf("%lld", &T);
	while (T--) {
		ans = 1999999999;
		scanf("%lld%lld", &n, &k);
		memset(vis, 0, sizeof(vis));
		ll x = n;
		top = 0;
		int cnt = 0;
		while (x) {
			stk[++top] = x % 10;
			x /= 10;
		}
		ll len = 0;
		for (int i = top; i >= 1; i--) {
			if (!vis[stk[i]]) {
				vis[stk[i]] = 1;
				cnt++;
				if (cnt == k) break;
			}
		}
		for (int i = top; i >= 1; i--) {
			if (!vis[stk[i]]) break;
			len = max(len, top - i + 1);
		}
		if (len == top) {
			printf("%lld\n", n);
			continue;
		} 
		int pre = 0, mx = 0;
		for (int i = top; i >= 1; i--) {
			pre = pre * 10 + stk[i];
			mx = 0;
			for (int l = 1; l <= 9; l++) {
				if (check(pre + l)) {
					for (int j = 0; j <= 9; j++) {
						if (vis[j]) {
							mx = j;
						 	break;
						}
					}
					ll res = pre+l;
					for (int j = i-1; j >= 1; j--) res = res * 10 + mx;
					ans = min(res, ans);
				} 
			}
		}
		printf("%lld\n", ans);
	}
}