前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >POJ 3252 Round Numbers(数位dp+前导零)

POJ 3252 Round Numbers(数位dp+前导零)

作者头像
Ch_Zaqdt
发布2019-01-28 11:04:29
5230
发布2019-01-28 11:04:29
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM

题目链接:http://poj.org/problem?id=3252

       题意是找出l到r范围中的二进制中0的个数大于等于1的有多少个。

       思路就是我们将它的二进制存起来,然后这里需要判断前导零的情况,不是很难理解,以dp[pos][n0][n1]分别来存第pos位,0的个数,1的个数,然后记忆化搜索就好了。


AC代码:

代码语言:javascript
复制
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 35
#define ll long long
using namespace std;
int a[maxn];
ll dp[maxn][maxn][maxn];

ll dfs(int pos, int n0, int n1, bool lead, bool limit){
	if(pos == -1){
		if(n0 >= n1) return 1;
		else return 0;
	}
	if(!limit && !lead && dp[pos][n0][n1] != -1) return dp[pos][n0][n1];
	int up = limit ? a[pos] : 1;
	ll ans = 0;
	for(int i=0;i<=up;i++){
		if(lead && i == 0) ans += dfs(pos - 1, 0, 0, true, limit && i == up);
		else{
			if(i == 0) ans += dfs(pos - 1, n0 + 1, n1, false, limit && i == up);
			else ans += dfs(pos - 1, n0, n1 + 1, false, limit && i == up);
		}
	}
	if(!limit && !lead) dp[pos][n0][n1] = ans;
	return ans;
}

ll solve(ll x){
	int pos = 0;
	while(x){
		a[pos ++] = x & 1;
		x >>= 1;
	}
	return dfs(pos - 1, 0, 0, true, true);
}

int main()
{
	ll l,r;
	scanf("%lld%lld",&l,&r);
	memset(dp, -1, sizeof(dp));
	printf("%lld\n", solve(r) - solve(l - 1));
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年01月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档