Codeforces Round #739 (Div. 3) F1. Nearest Beautiful Number (easy version)

在这里插入图片描述

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值