sdut 2609 A-Number and B-Number

A-Number and B-Number

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

    Tom is very interested in number problem. Nowadays he is thinking of a problem about A-number and B-number.
    A-number is a positive integer whose decimal form contains 7 or it can be divided by 7. We can write down the first 10 A-number ( a[i] is the ith A-number) 
         {a[1]=7,a[2]=14,a[3]=17,a[4]=21,a[5]=27,a[6]=28,a[7]=35,a[8]=37,a[9]=42,a[10]=47};
    B-number is Sub-sequence of A-number which contains all A-number but a[k] ( that k is a  A-number.)  Like 35, is the 7th A-number and 7 is also an A-number so the 35 ( a[7] ) is not a B-number. We also can write down the first 10 B-number.

         {b[1]=7,b[2]=14,b[3]=17,b[4]=21,b[5]=27,b[6]=28,b[7]=37,b[8]=42,b[9]=47,b[10]=49};
    Now Given an integer N, please output the Nth B-number

输入

The input consists of multiple test cases.

For each test case, there will be a positive integer N as the description.

输出

For each test case, output an integer indicating the Nth B-number.

You can assume the result will be no more then 2^63-1.

示例输入

17100

示例输出

737470

提示

 

来源

 2013年山东省第四届ACM大学生程序设计竞赛

示例程序

 数位dp处理出a数组个数
二分找到第x个b数组为a数组中的id
在二分找到对应的a数组的值
要用ull 不然会错
ACcode
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll unsigned long long
#define mid ((l+r)>>1)
using namespace std;
ll dp[19][2][7];
int data[19];
inline ll dfs(int len,bool is_7,int mod_7,int limit){
    if(!len)return (is_7||(mod_7==0));
    if(!limit&&dp[len][is_7][mod_7]!=-1)return dp[len][is_7][mod_7];
    int ed=limit?data[len]:9;
    ll ans=0;
    for(int i=0;i<=ed;++i)
        ans+=dfs(len-1,is_7||i==7,(mod_7*10+i)%7,limit&&i==ed);
    return limit?ans:dp[len][is_7][mod_7]=ans;
}
inline ll fun(ll n){
    int len=0;
    while(n){
        data[++len]=n%10;
        n/=10;
    }
   return dfs(len,0,0,1)-1;
}
void doit(ll n){
    ll l=n,r=((long long)1<<63);
    ll add;
    while(l<r){
        ll tmp=mid-fun(mid);
        if(tmp==n){
            for(ll k=l;k<=mid;++k)
                if(k-fun(k)==n){
                    add=fun(k);
                    break;
                }
            break;
        }
        if(tmp>n)r=mid;
        else l=mid;
    }
    l=0,r=((long long)1<<63);
    n+=add;
    while(l<r){
        ll tmp=fun(mid);
        if(tmp==n){
           for(ll k=l;k<=mid;++k)
            if(fun(k)==tmp){
               cout<<k<<'\12';
             return;
           }
        }
        if(tmp<n)l=mid;
        else r=mid;
    }
}
int main(){
    ll n;memset(dp,-1,sizeof(dp));
    ios::sync_with_stdio(false);
    while(cin>>n)doit(n);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值