poj 3252 数位dp 记忆化搜索 二进制 前导0

要求:一个数的二进制数的0的个数大于等于1的个数,则这个数称为"round number",问[a,b]有多少"round number"。

方法:数位dp 记忆化搜索

1.dp[i][j][k]示i位数 j个0 k个1的个数。

2.套路记忆化搜索即可,细节在代码中说明。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
long long dp[40][40][40] ;
//dp[i][j][k]示i位数 j个0 k个1的个数 
int digit[40] ;
long long dfs(int len , int num0 , int num1 , int lim , int bz)
{
//len 表示当前的位数 
//num0 记录遍历到当前位时前面的0出现的个数
//num1 记录遍历到当前位时前面的1出现的个数
//lim 当前位是否有上限
//bz 是否前面已经有1 若前面没有1 则num0不会增加 
    int i , j ;
    int num ;
    int ans = 0 ;
	if(len <= 0)//搜索到底层 
	   return num0 >= num1 ;
	if(!lim && bz == 1 && dp[len][num0][num1] != -1)//若满足条件且已搜索过
	   return dp[len][num0][num1] ;
	if(lim) //若有上限,则可取到这个数的此位数 
	   num = digit[len] ;//num表示当前位的上限 
	else   //若无上限,则可取到1 
	   num = 1 ;
	for(i = 0 ; i <= num ; i ++)
	{
	   if(bz == 0)//前面没有1 
	   {
	   	 if(i == 0)
	      ans += dfs(len - 1 , num0 , num1 , lim && i == num , 0) ; //前面没有1且当前位为0,则num0不增加。 
	     else
	      ans += dfs(len - 1 , num0 , num1 + 1 , lim && i == num , 1) ;	
	   }
	   else//前面有1 
	   {
	     if(i == 0)
	      ans += dfs(len - 1 , num0 + 1 , num1 , lim && i == num , 1) ;
	     else
	      ans += dfs(len - 1 , num0 , num1 + 1 , lim && i == num , 1) ;		
	   }   	
	}   
	if(!lim && bz == 1) 
	   dp[len][num0][num1] = ans ;//已经搜索过的不用再次搜索 
	return ans ; 
}
long long solve(long long x)
{
	  int len ;
      len = 0 ;
	  while(x)
      {
      	digit[++len] = x % 2 ;
      	x /= 2 ;
	  }
      return dfs(len , 0 , 0 , 1 , 0) ;
}
int main()
{
	int t ;
	int i , j , k ;
	int a , b ;
	int ans ;
	memset(dp , -1 , sizeof(dp)) ;
    scanf("%d%d" , &a , &b) ;
    ans = solve(b) - solve(a - 1) ;//因为solve(x)返回的是1~x的值,因此计算a时需要传递参数a-1。 
    printf("%d" , ans) ;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值