题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3943
题目来源:某人帖子上扒来的,2011多校题。
简要题意:求 (P,Q] 中第 Ki 个含有 X 个
4 和 Y 个7 的数数据范围: T⩽100;0⩽X+Y⩽20;0<P⩽Q<2631⩽N⩽100;0<Ki<263
题解
属于一眼可以看出是数位dp的题目。
dp[i][j][k] 为第 i 位有
j 个 4,k 个 7 的方案数。转移的时候就按照当前这位是
4,7 其他分情况讨论就行了。
实现
对于找不到的情况直接开始的时候特判。
找得到的话由于范围可能很大需要二分。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
LL dp[25][25][25];
int num[25];
LL dfs(int pos, bool e, int four, int seven) {
if (pos == -1) return four==0 && seven == 0;
if (four < 0 || seven < 0) return 0;
if (!e && dp[pos][four][seven] != -1) return dp[pos][four][seven];
LL ans = 0;
int lim = e ? num[pos] : 9;
for (int i = 0; i <= lim; i++) {
if (i == 4) ans += dfs(pos-1, e&&lim==i, four-1, seven);
else if (i == 7) ans += dfs(pos-1, e&&lim==i, four, seven-1);
else ans += dfs(pos-1, e&&lim==i, four, seven);
}
if (!e) dp[pos][four][seven] = ans;
return ans;
}
LL query(LL x, int four, int seven) {
int len = 0;
while (x) {
num[len++] = x%10;
x /= 10;
}
return dfs(len-1, true, four, seven);
}
void solve(LL l, LL r, LL k, int four, int seven) {
k += query(l, four, seven);
if (query(r, four, seven) < k) {
puts("Nya!");
return;
}
LL ans = ++l;
while (l <= r) {
LL mid = (l+r)>>1;
if (query(mid, four, seven) >= k) {
ans = mid;
r = mid-1;
} else {
l = mid+1;
}
}
printf("%I64d\n", ans);
}
int main() {
memset(dp, -1, sizeof dp);
int t, n, x, y, cas = 1;
LL l, r, k;
scanf("%d", &t);
while (t--) {
scanf("%I64d%I64d%d%d%d", &l, &r, &x, &y, &n);
printf("Case #%d:\n", cas++);
for (int i = 0; i < n; i++) {
scanf("%I64d", &k);
solve(l, r, k, x, y);
}
}
return 0;
}