BNU 26351 Space Elevator 数位dp

Problem E
Space Elevator
China is building a space elevator, which will allow the launching probes and satellites to a much
lower cost, enabling not only scientific research projects but also space tourism.
However, the Chinese are very superstitious, and therefore have a very especial care with the
numbering of floors in the elevator: they do not use any number containing the digit “4” or the
sequence of digits “13”. Thus, they do not use the fourth floor or the floor 13 or the floor 134 nor the
floor 113, but use the floor 103. Thus, the first floors are numbered 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 15,
16, . . .
As the space elevator has many levels, and levels must be numbered, the Chinese asked you to
write a program that, given the level, indicates which number should be assigned to it.
Input
The input contains several test cases. Each test case consists of a single line containing an integer
N which indicates the floor whose number should be determined.
Output
For each test case, print a line containing a single integer indicating the number assigned to the
N-th floor.
Restrictions
• 1 ≤ N ≤ 1018
Examples
Sample input
1
4
11
12
440
Sample output
1
5
12
15

666

题意,从小到大,去掉有4和13的数,要求第n位数是多少。

用dp[l][t]表示长为l位的,t = 0表示没有限制 t =1 表示最后一位是1,t = 2表示结束为4或者是13的个数。则任何一个数,都可以很快转化成dp[l][t]来求解,如果是同一位数,很对应的那么数开始计数,否则从9开始计数,记忆化搜索就可以了。得到了个数,可以用个二分的方法,找到答案就可以了。不过这题有个坑,如果是10^18这个数,就是用long long是会爆的,要用unsinged long long,总的复杂度为log(n0) * log(n)

#define N 100
#define ll unsigned long long
#define INF 18223372036854775800
ll pri[N],dp[N][3];
ll get(ll d,ll t){
    if(d==2||t==4||(d==1&&t==3))return 2ll;
    if(t==1)return 1ll;
    return 0ll;
}
ll dfs(ll pos,ll d,ll flag){
    if(pos==0)return d==2;
    if(!flag&&dp[pos][d]!=-1)return dp[pos][d];
    ll u=flag?pri[pos]:9,ans=0;
    for(ll i=0;i<=u;i++)
    ans+=dfs(pos-1,get(d,i),flag&&(i==u));
    return flag?ans:dp[pos][d]=ans;
}
ll solve(ll x){
    ll cnt=0,tx = x;
    while(x){
        pri[++cnt]=x%10;
        x/=10;
    }
    ll temp = tx - dfs(cnt,0,1);
    return temp;
}
ll getans(ll n){
    ll l = 1,r = INF,mid;
    while(l < r - 1){
        mid = l + (r - l)/2;
        ll x = solve(mid);
        if(x < n) l = mid;
        else r = mid;
    }
    if(solve(l) == n) return l;
    if(solve(r) == n) return r;

    return 0;
}
int main()
{
    ll n;
    memset(dp,-1,sizeof(dp));
    while(cin>>n){
        ll temp = getans(n);
        cout<<temp<<endl;
    }
    return 0;
}


你可能感兴趣的:(BNU 26351 Space Elevator 数位dp)