BNU 26351 Space Elevator 数位dp

32 篇文章 0 订阅
24 篇文章 0 订阅
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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值