Google Code Jam 2017 Qualification Round Problem B. Tidy Numbers

Problem

Tatiana likes to keep things tidy. Her toys are sorted from smallest to largest, her pencils are sorted from shortest to longest and her computers from oldest to newest. One day, when practicing her counting skills, she noticed that some integers, when written in base 10 with no leading zeroes, have their digits sorted in non-decreasing order. Some examples of this are 8, 123, 555, and 224488. She decided to call these numbers tidy. Numbers that do not have this property, like 20, 321, 495 and 999990, are not tidy.

She just finished counting all positive integers in ascending order from 1 to N. What was the last tidy number she counted?

Input

The first line of the input gives the number of test cases, TT lines follow. Each line describes a test case with a single integer N, the last number counted by Tatiana.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the last tidy number counted by Tatiana.

Limits

1 ≤ T ≤ 100.

Small dataset

1 ≤ N ≤ 1000.

Large dataset

1 ≤ N ≤ 1018.

Sample


Input 
 

Output 
 
4
132
1000
7
111111111111111110

Case #1: 129
Case #2: 999
Case #3: 7
Case #4: 99999999999999999

Note that the last sample case would not appear in the Small dataset.


不动脑构造的写法,数位dp+二分

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
typedef long long ll;
typedef pair<int,int> P;

ll dp[20][12];

int a[20];

ll dfs(int pos,int pre,bool limit){
    if(pos==-1) return 1;
    if(dp[pos][pre]!=-1&&!limit) return dp[pos][pre];
    int up=limit?a[pos]:9;
    ll res=0;
    for(int i=0;i<=up;i++){
        if(i>=pre) res+=dfs(pos-1,i,limit&&i==up);
    }
    if(!limit) dp[pos][pre]=res;
    return res;
}

ll solve(ll x){
    int pos=0;
    while(x){
        a[pos++]=x%10;
        x/=10;
    }
    return dfs(pos-1,0,1);
}

int main(){
    memset(dp,-1,sizeof(dp));
    int T;
    cin>>T;
    int casi=1;
    while(T--){
        ll x;
        cin>>x;
        ll tmp=solve(x);
        ll l=-1;ll r=x+1;
        while(r-l>1){
            ll mid=(r+l)>>1;
            if(solve(mid)<tmp) l=mid;
            else r=mid;
        }
        printf("Case #%d: %lld\n",casi++,r);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值