F2. Nearest Beautiful Number (hard version) (贪心)
注意到一个结论:答案和 n n n同位数,因为当所有位都为 9 9 9必定满足。
然后就可以贪心,找到满足不同位数 ≤ k \le k ≤k的最大前缀 + 1 +1 +1的位置,显然此位需要加1,后面的位全部修改为 0 0 0,然后修改 n n n,直到 n n n满足条件为止。
e p : n = 4561 , k = 3 ep: n=4561,k=3 ep:n=4561,k=3
最大前缀是
456
456
456,需要对
1
1
1加不断
1
1
1,直到
n
=
4564
n=4564
n=4564满足情况返回。
e
p
:
n
=
4512
,
k
=
2
ep:n=4512,k=2
ep:n=4512,k=2。
最大前缀 45 45 45,第三位的 1 1 1加 1 1 1,后面置为 0 0 0, n = 4520 n=4520 n=4520,然后再重新模拟。
n → 4530 → 4540 → 4544 n\rightarrow 4530\rightarrow 4540\rightarrow 4544 n→4530→4540→4544。
设 n n n的位数是 m m m位。
每位最多修改 10 10 10次,每次遍历最多 m m m位,最多遍历 m m m次。
时间复杂度: O ( 10 m 2 ) O(10m^2) O(10m2)
#include <bits/stdc++.h>
using namespace std;
string solve(){
string n;
int k;
cin >> n >> k;
while (true)
{
set<char> s;
for (auto c : n) s.insert(c);
if (s.size() <= k) return n;
s.clear();
int ptr = 0;
for (; ; ptr++)
{
s.insert(n[ptr]);
if (s.size() > k)
{
while (n[ptr] == '9')
ptr--;
n[ptr]++;
for (int i = ptr + 1; i < n.size(); i++)
n[i] = '0';
break;
}
}
}
}
int main(){
int t;
cin >> t;
while (t--)
cout << solve() << '\n';
return 0;
}