[poj3252]Round Numbers_数位dp

Round Numbers poj3252

    题目大意:求一段区间内Round Numbers的个数。

    注释:如果一个数的二进制表示中0的个数不少于1的个数,我们就说这个数是Round Number.给定区间l,r<=$2\cdot 10^9$。

      想法:又是一道数位dp裸题。我们先来设状态:dp[i]表示二进制表示下有i为而且第一位是1的Round Number的个数。

        这题的特殊之处在于我们并不需要转移?因为我们可以直接求出任意的dp[i]。显然,我们的i位数的第一位是1,所以,后面0的个数一定不能少于(i-1)/2+1.我们在后面的i-1位当中去组合数即可。

      然后,我们思考数位dp的边界:对于一个数来讲,我们可以将所有的位数小于tot的dp全部加起来(tot是该数的二进制表示下的位数)。然后,我们显然只需要对于这个数的二进制从左到右枚举:弄两个计数器分别记录之前经过了多少个0.对于当前数码,如果是0,略过即可。如果是1,则在它之后所有满足该位是0前面满足的数的Round Number都是满足条件的Round Number。,统计即可。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int C[33][33];
void before_hand()//预处理组合数
{
	C[0][0]=1;
	C[1][0]=1;C[1][1]=1;
	for(int i=2;i<33;i++)
	{
		C[i][0]=1;
		for(int j=1;j<i;j++)
			C[i][j]=C[i-1][j-1]+C[i-1][j];
		C[i][i]=1;
	}
}
int bits[33];
int dispose(int n)
{
	if(n<=1) return 0;
	int tot=0;
	while(n>0)//二进制拆分
	{
		if(n&1) bits[tot++]=1;
		else bits[tot++]=0;
		n>>=1;
	}
	int ans=0;
	for(int i=tot-1;i>0;i--)//将位数小于tot的全部加一起
	{
		if(i%2==0)
			ans+=((1<<(i-1)))/2;
		else
			ans+=((1<<(i-1))-C[i-1][(i-1)/2])/2;
	}
	int count_for_0=0,count_for_1=0;//两个计数器(字面意思)
	for(int i=0;i<tot;i++)
	{
		if(bits[i]==0) count_for_0++;
		else count_for_1++;
	}
	if(count_for_0>=count_for_1) ans++;
	count_for_0=0;
	count_for_1=1;
	for(int i=tot-2;i>=0;i--)
	{
		if(bits[i]==1)
		{
			for(int j=i;j>=0&&j+count_for_0+1>=i-j+count_for_1;j--)
				ans+=C[i][j];//简单点儿来说就是直接统计后面的dp值
			count_for_1++;
		}
		else count_for_0++;//如果是0,就直接增加计数器
	}
	return ans;
}

int main()
{
	before_hand();
	int a,b;
	while(scanf("%d%d",&a,&b)!=EOF)
	{
		printf("%d\n",dispose(b)-dispose(a-1));//防止重叠
	}
	return 0;
}

    小结:数位dp的恶心之处就是边界特判,沉下心来写一写,不行就把代码拿去copy算了,毕竟这道题的本质不是代码... ...

原文地址:https://www.cnblogs.com/ShuraK/p/8560401.html

时间: 2024-08-30 00:06:12

[poj3252]Round Numbers_数位dp的相关文章

POJ 3252 Round Numbers(数位dp&amp;amp;记忆化搜索)

题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于一个二进制数的最高位必须为1.所以设置变量first记录前面位是否有1,若有1,则可随意放,否则,仅仅可放1. 同一时候.上面的推断决定了搜索时len的大小与二进制本身的长度不一定相等,所以需两个变量对1和0的个数进行记录. 用dp[a][b][c]保存长度a,b个0,c个1的数字个数.记忆化搜索.

POJ Round Numbers(数位DP)

题目大意: Round Number:  将一个整数转化为二进制数字后,(不含前导0) 要是0的个数 大于等于1的个数 则是 Round Number 问从L-R之中有多少个Round Number 题目分析: 要转化为2进制数字,我们用10进制保存明显不好判断0和1的个数,所以选择用8进制来存储,这样的话每一次进位会多出 ”000“, 然后再加上8进制的尾数, 最后我们可以得出增加了几个 1 和 增加了 几个 0 需要注意的一点就是, 当前面的数字小于 8 的时候 我们要对 前导 0 进行特殊

poj 3252 Round Number 数位dp

Round Numbers Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11481   Accepted: 4305 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors',

POJ 3252 Round Numbers (数位DP)

题意:求区间内一个数二进制位1的数量大于等于0的数的个数. 析:dp[i][j][k] 表示前 i 位,长度为 j 的,1的数量是 k.注意前导0. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <

POJ 3252 round numbers(数位DP)

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <vector> #include <queue> #include <cstring> #include <set> #include <stack> #include <m

POJ 3252 Round Numbers 数位dp(入门

题目链接:点击打开链接 题意: 给定一个区间,求区间内有多少个合法数(当这个数的二进制中0的个数>=1的个数称为合法数 二进制无前导0) 思路: cnt[i]表示二进制长度为i位(即最高位为1,其他位任意)时的合法数个数. sum[i] 就是二进制长度<=i位的合法数个数. 然后从最高位枚举到低位即可.维护当前0的个数. #include <cstdio> #include <algorithm> #include <cstring> #include &l

hdu 5179(数位DP||打表)

beautiful number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 596    Accepted Submission(s): 370 Problem Description Let A=∑ni=1ai∗10n−i(1≤ai≤9)(n is the number of A's digits). We call A as “

POJ-3252 Round Numbers (数位DP)

Round Numbers http://poj.org/problem?id=3252 Time Limit: 2000MS   Memory Limit: 65536K       Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro,

POJ3252 Round Numbers 组合数学||数位DP

这题目做了两个小时,调试的头都晕了... 题型是数位DP中很常见的,给一个区间[l,r]求区间[l,r]中的 符合题目要求的数的个数,本题求的 是 区间中 的数  它的二进制中0的个数大于等于1的个数的    这些数的个数,不好意思表达能力有点差...例如[1,4]答案是2, 因为 2的二进制是10,0的个数大于等于1的个数,4的二进制是100,0的个数大于1的个数,所以答案是两个 好了第一反应肯定是 设定一个函数 f(r) - f[l - 1]就是答案,那么显然这个函数f(r)的意思就是 1