F1. Nearest Beautiful Number (easy version)
题意:
题目读假了
导致wa了14遍
然后赛后看数据
1 2
竟然是1不是10???????
题目给1e4个询问
每次给n,k
找到第一个大于等于n的数x
满足x的所有不同数字的个数<= k
1 <= k <= 2 , 1 <= n <= 1e9
思路:
k = 1 的时候 直接暴力
主要是k=2的时候比较麻烦
考虑一下预处理出所有的k=1和k=2的数字
用状态压缩优化
时间复杂度 10 * 10 * 10 * 2^9 * 10
完全可以接受
然后对于每一个n
二分找到第一个大于等于它的数即可
具体细节可以看代码
时间复杂度:O 10 * 10 * 10 * 2^9 * 10
#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define re register int
#define pll pair<int,int>
#define x first
#define y second
#define sf(x) scanf("%d",&x)
#define sfl(x) scanf("%lld",&x)
#define de(x) cout << x << "\n" ;
typedef long long ll ;
using namespace std;
const int N = 1e7 + 10 , M = 2010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int get(string a)
{
int res = 0 ;
for(int i = 0 ; i < a.size() ; i ++)
{
res = res * 10 + a[i] - '0' ;
}
return res ;
}
int x[N] ;
int main()
{
int t ;
cin >> t ;
int z = 0 ;
for(char p = '0' ; p <= '9'; p ++) //枚举第一个数字
{
for(char q = '0' ; q <= '9' ; q ++) //枚举第二个数字
{
for(int len = 0 ; len <= 9 ; len ++) // 枚举数的长度
{
for(int i = 0 ; i <= (1 << len) - 1 ; i ++) // 枚举二进制数
{
int res = 0 ;
for(int j = 0 ; j < len ; j ++) // 判断
{
if(i >> j & 1)
{
res = res * 10 + p - '0' ;
}
else res = res * 10 + q - '0' ;
}
x[++ z] = res ;
}
}
}
}
/*
上面的过程在解释一下
比如len = 3 的时候
p = 3 , q = 4
一共有8种情况分别是
333 334 343 344 433 434 443 444
我们用一个长度为3的二进制数来表示状态
_ _ _
1 0 1
1表示这个位置填p
0表示这个位置填q
那么101对应的数字便是 343
从000 - 001 - 010 - 011 - 100 - 101 - 110 - 111
这8种状态就对应了8种不一样的填法
*/
x[++ z] = 1000000000 ;
// 最大的10位数
sort(x + 1 , x + 1 + z) ;
int cnt = unique(x + 1 , x + 1 + z) - x;
// 排序去重
// 也可以不去 无所谓
while(t--)
{
int n , k ;
cin >> n >> k ;
if(k == 1)
{
// k = 1 暴力
int ans = 2e9 ;
string s = to_string(n) ;
int n = s.size() ;
for(char i = '0' ; i <= '9' ; i ++)
{
string res = "" ;
for(int j = 1 ; j <= n ; j ++)
{
res += i ;
}
if(get(res) >= get(s)) ans = min(ans,get(res)) ;
}
de(ans) ;
}
else
{
// 二分找到第一个大于等于n的数
int xia = lower_bound(x + 1 , x + 1 + cnt , n) - x ;
cout << x[xia] << "\n" ;
}
}
return 0;
}