hihocoder #1301 : 筑地市场 二分+数位dp

来源:互联网 发布:小视频配音软件 编辑:程序博客网 时间:2024/06/05 22:36

题目链接:这里
题意:
Description

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

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

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

输入数据包含一行一个整数 k(k ≤ 1018)。
Output

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

19
Sample Output

54

解法:
二分之后数位DP去check就可以了,这道题就变成了给你x,问你小于等于x里面有多少个数,含有4或者7。

//Hihocoder 1301 二分+数位DP#include <bits/stdc++.h>using namespace std;long long k;long long dp[22][2];int digit[22];long long dfs(int l, int flag, bool jud){    if(l == 0){        return flag;    }    if(!jud && dp[l][flag] != -1) return dp[l][flag];    int nex = jud ? digit[l] : 9;    long long ans = 0;    for(int i = 0; i <= nex; i++){        ans += dfs(l-1, flag||(i==4)||(i==7), jud&&(i==nex));    }    if(!jud) dp[l][flag] = ans;    return ans;}long long f(long long x){    int num = 0;    while(x){        digit[++num] = x%10;        x /= 10;    }    memset(dp, -1, sizeof(dp));    return dfs(num, 0, 1);}int main(){    scanf("%lld", &k);    long long l = 1, r = 2e18, ans;    while(l <= r){        long long mid = (l+r)/2;        if(f(mid)>=k) r=mid-1, ans=mid;        else l = mid+1;    }    printf("%lld\n", ans);    return 0;}
0 0