「HDU 3943」K-th Nya Number 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3943


题意大意:

求区间内第 k k k个有且仅有 x x x个4和 y y y个7的数


思路:

很明显的数位 D P DP DP……

因为要求第 k k k个符合条件的数,继而想到二分查找答案

详情见代码。。。


完整代码:

#include<cstdio>
#include<cstring> 
#include<algorithm>
#define ll long long
using namespace std;
const ll N = 31;
ll t,p,q,x,y,n,tot,num[N],f[N][N][N];//一共有i位数,有j位4,k位7 

ll dfs(ll pos, ll pre, ll pre2, bool flag) {//位置,已经有了pre个4,pre2个7, 
	if(!pos) return pre == x && pre2 == y;//如数位为0,退出,判断当前答案是否符合条件 
	if(pre > x || pre2 > y) return 0;//不符条件 
	if(f[pos][pre][pre2] != -1 && !flag) return f[pos][pre][pre2];//记忆化 
	ll end = flag ? num[pos] : 9;//确定范围 
	ll res = 0; 
	for(ll j = 0; j <= end; j ++) {
		if(j == 4) res += dfs(pos - 1, pre + 1, pre2, flag && end == j);//找到4的情况 
		else if(j == 7) res += dfs(pos - 1, pre, pre2 + 1, flag && end == j);//7 
		else res += dfs(pos - 1, pre, pre2, flag && end == j);//没找到 
	}
	if(!flag) f[pos][pre][pre2] = res;//记忆化 
	return res;
}
ll work(ll m) {
	tot = 0;
	while(m) num[++tot] = m % 10,m /= 10;//拆分数位 
	return dfs(tot,0,0,1); 
}
ll solve(ll left,ll k) {
	ll l = p + 1,r = q;//二分 
	while(l < r) {
		ll mid = (l + r) / 2;
		if(work(mid) >= k + left) r = mid;
		else l = mid + 1;
	}
	return l;//返回结果 
}

int main() {
	
	scanf("%lld",&t);
	for(ll i = 1; i <= t; i ++) {
		scanf("%lld %lld %lld %lld %lld",&p,&q,&x,&y,&n);
		memset(f,-1,sizeof(f));//初始化 
		printf("Case #%lld:\n",i);
		ll ans1 = work(q) , ans2 = work(p), ans3;//先求出小于等于p的符合条件的数的个数和大于q的个数 
		ans3 = ans1 - ans2;//区间内的数 
		while(n--) {
			ll h;
			scanf("%lld",&h);
			if(ans3 < h) printf("Nya!\n");//如果个数小于k,找不到第k大的数 
			else printf("%lld\n",solve(ans2,h));//否则二分查找 
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值