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

题目链接:

http://hihocoder.com/problemset/problem/1301?sid=804672

题解:

二分答案,每次判断用数位dp做。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

typedef long long LL;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;

//dp[x][0]表示高位还没有出现4,7。
//dp[x][1]表示高位已经出现4,7了。
LL dp[22][2];
bool vis[22][2];
LL k;

int num[22];
//z表示高位是不是刚好在最大的边界上。
LL dfs(int cur, int y, int z) {
    if (cur == -1 && y) return 1;
    if (cur == -1) return 0;
    if (vis[cur][y] && !z) return dp[cur][y];
    int e = z ? num[cur] : 9;
    LL res = 0;
    for (int i = 0; i <= e; i++) {
        res += dfs(cur - 1, y || i == 4 || i == 7, z && (i == e));
    }
    if (!z) {
        dp[cur][y] = res;
        vis[cur][y] = 1;
    }
    return res;
}

bool ok(LL x) {
    int tot = 0;
    while (x) {
        num[tot++] = x % 10;
        x /= 10;
    }
    memset(dp, 0, sizeof(dp));
    memset(vis, 0, sizeof(vis));
    LL res = dfs(tot - 1, 0, 1);
    return res<k;
}

int main() {
    while (scanf("%lld", &k) == 1) {
        LL l = 1, r = INFLL;
        //printf("r:%lld\n", r);
        while (l + 1 < r) {
            LL mid = l + (r - l) / 2;
            if (ok(mid)) l = mid;
            else r = mid;
        }
        printf("%lld\n", l + 1);
    }
    return 0;
}
时间: 2024-08-04 23:38:09

hihocoder #1301 : 筑地市场 数位dp+二分的相关文章

[数位dp+二分] fzu 1074 Nancy&#39;s Birthday

题意:给m,n,问含有m个0的第k个数,是几位数,并且最高位是多少. 思路:和普通数位dp一样,加上个二分. 然后就是注意一下,极限值测试下能否算出来,这题极限值很大! 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #

poj3208 Apocalypse Someday 数位dp+二分 求第K(K &lt;= 5*107)个有连续3个6的数。

/** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. 思路:数位dp+二分. dp[i][j]表示长度为i,前缀状态为j时含有的个数. j=0表示含有前导0: j=1表示前缀连续1个6 j=2表示前缀连续2个6 j=3表示前缀连续3个6 j=4表示前缀不是6: */ //#include<bits/stdc++.h> #include<cstr

[数位dp+二分] zoj Generalized Palindromic Number

题意: 找一个小于N的最大的且符合题意的数. 题意的数为,通过缩减后是回文的数,所谓的缩减就是相同连续的数看做一个数,如"155451111"其实就是"15451"是符合题意的数. 思路: 通过数位dp,然后二分求解. dp[i][j][k]代表第i位,已经放了j个数,最后长度是k的缩减回文数有几个. 然后需要一个ok[]数组代表放的数是什么,如果连续放相同的数就等于没放数. 遍历所有的长度就可以得到结果了. 其实不难发现,这种回文数一定是奇数位的. 代码: #in

[uva 1350]数位dp+二分

题目链接:https://vjudge.net/problem/38405 #include<bits/stdc++.h> using namespace std; long long dp[64][2]; int b[64]; long long dfs(int pos,int preok,int pre1) { if (pos==-1) return 1; if (preok && dp[pos][pre1]!=-1) return dp[pos][pre1]; int u

HDU 3943 K-th Nya Number(数位dp+二分)

Problem Description Arcueid likes nya number very much. A nya number is the number which has exactly X fours and Y sevens(If X=2 and Y=3 , 172441277 and 47770142 are nya numbers.But 14777 is not a nya number ,because it has only 1 four). Now, Arcueid

ACM学习历程—HDU5587 Array(数学 &amp;&amp; 二分 &amp;&amp; 记忆化 || 数位DP)(BestCoder Round #64 (div.2) 1003)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5587 题目大意就是初始有一个1,然后每次操作都是先在序列后面添加一个0,然后把原序列添加到0后面,然后从0到末尾,每一个都加上1. 例如:a0, a1, a2 => a0, a1, a2, 1, a0+1, a1+1, a2+1 题解中是这么说的:“ 其实Ai为i二进制中1的个数.每次变化A{k+2^i}=A{k}+1,(k<2^?i??)不产生进位,二进制1的个数加1.然后数位dp统计前m个数二

[hihocoder 1033]交错和 数位dp/记忆化搜索

#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0,?a1,?...,?an?-?1,定义交错和函数: f(x)?=?a0?-?a1?+?a2?-?...?+?(?-?1)n?-?1an?-?1 例如: f(3214567)?=?3?-?2?+?1?-?4?+?5?-?6?+?7?=?4 给定 输入 输入数据仅一行包含三个整数,l,?r,?k(0?≤?l?≤?r?≤?1018,?|k|

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

hihoCoder #1033 : 交错和 [ 数位dp ]

传送门 #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1 例如: f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = k 的 x 的和,即