#1301 : 筑地市场

#1301 : 筑地市场

时间限制:7000ms
单点时限:1000ms
内存限制:256MB

描述

筑地市场是位于日本东京都中央区筑地的公营批发市场,为东京都政府设置的中央批发市场之一,亦是日本最大的鱼市场。其规模之大与知名度之广,不只是东京,更是日本首屈一指的批发市场。全球百分之五十的金枪鱼,从世界的各地被运往这里,在每天的清晨,进行着繁忙的拍卖,它们是寿司中最不可或缺的食材,如何能够买到上等的金枪鱼,成为了每家寿司店都关注的大事。

当地的鱼贩,会取出鱼腹的一小块进行观察,以辨别鱼品质的好坏...

我们将取出的小块可以看成是一个十进制数字串(没有前缀0),其中包含数字4或者7的数字串,被认为是好的。岛娘想知道所有的数字串中,数字串转为十进制数后排第 k 小(从1开始)的好字符串是多少,你可以帮助她吗?

输入

输入数据包含一行一个整数 kk ≤ 1018)。

输出

输出数据包含一行,表示对应的十进制数字串。

样例输入
19
样例输出
54
分析:二分+裸数位dp;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=1e5+10;
const int N=5e4+10;
const int M=N*10*10;
using namespace std;
inline ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
inline ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
inline void umax(ll &p,ll q){if(p<q)p=q;}
inline void umin(ll &p,ll q){if(p>q)p=q;}
int n,m,k,t,num[20],pos;
ll dp[20][2],p;
ll dfs(int pos,int x,int y)
{
    if(pos<0)return x;
    if(y&&dp[pos][x]!=-1)return dp[pos][x];
    int now=y?9:num[pos],i;
    ll ret=0;
    rep(i,0,now)
    {
        ret+=dfs(pos-1,x||i==4||i==7,y||i<num[pos]);
    }
    return y?dp[pos][x]=ret:ret;
}
ll gao(ll x)
{
    pos=0;
    while(x)num[pos++]=x%10,x/=10;
    return dfs(pos-1,0,0);
}
int main()
{
    int i,j;
    memset(dp,-1,sizeof(dp));
    scanf("%lld",&p);
    ll l=1,r=9e18,ret;
    while(l<=r)
    {
        ll mid=l+r>>1;
        if(gao(mid)>=p)ret=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%lld
",ret);
    return 0;
}
原文地址:https://www.cnblogs.com/dyzll/p/6406009.html