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

时间:2023-03-09 16:27:37
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[][];
bool vis[][];
LL k; int num[];
//z表示高位是不是刚好在最大的边界上。
LL dfs(int cur, int y, int z) {
if (cur == - && y) return ;
if (cur == -) return ;
if (vis[cur][y] && !z) return dp[cur][y];
int e = z ? num[cur] : ;
LL res = ;
for (int i = ; i <= e; i++) {
res += dfs(cur - , y || i == || i == , z && (i == e));
}
if (!z) {
dp[cur][y] = res;
vis[cur][y] = ;
}
return res;
} bool ok(LL x) {
int tot = ;
while (x) {
num[tot++] = x % ;
x /= ;
}
memset(dp, , sizeof(dp));
memset(vis, , sizeof(vis));
LL res = dfs(tot - , , );
return res<k;
} int main() {
while (scanf("%lld", &k) == ) {
LL l = , r = INFLL;
//printf("r:%lld\n", r);
while (l + < r) {
LL mid = l + (r - l) / ;
if (ok(mid)) l = mid;
else r = mid;
}
printf("%lld\n", l + );
}
return ;
}