poj 3252 数位dp(dfs写法) 二进制0出现比1多的数字个数

题意:给定一个区间[n,m],求这个区间内的round数的数量。所谓round数,就是这个数的二进制表示(不含前导零)中0出现的个数不比1出现的个数少。前几个Round数:0,2,4,8,9,10,12。

思路:dp。dfs(int k,int hasone,int numone,int limit)这几个参数的意思是:

k:当前处理的是第几位

hasone:之前是否出现过1

numone:之前出现的数字1的数量,可以为负数,所以off函数就是将这个数映射到整数区间。

limit:是否有上界。

其中dp数组的第三维分为是否之前出现过1,这个不要忘记。比如dfs(2,0,0,0)和dfs(2,1,0,0)这两个返回值应该是不一样的。前者之前没有出现过1,所以不能有前导零,合理的只有0和10.而后者合理的有三个:0,01,10

#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
using namespace std;
int n,m;
int d[35],len;
int dp[32][64][2];
int off(int x){
    return x+32;
}
int dfs(int k,int hasone,int numone,int limit){
    if(k==0)
        return numone<=0;
    if(!limit && dp[k][off(numone)][hasone]!=-1)
        return dp[k][off(numone)][hasone];
    int res = 0;
    if(limit){
        if(d[k]==0)
            res += dfs(k-1,hasone,numone-hasone,1);
        else
            res += dfs(k-1,hasone, numone-hasone, 0) + dfs(k-1,1,numone+1,1);
    }else
        res += dfs(k-1, hasone, numone-hasone, 0) + dfs(k-1, 1, numone+1, 0);
    if(limit == 0)
        dp[k][off(numone)][hasone] = res;
    return res;
}
int solve(int x){
    len = 0;
    while(x){
        d[++len] = x&1;
        x>>=1;
    }
    return dfs(len,0,0,1);
}
int main(){
    memset(dp,-1,sizeof(dp));
    while(scanf("%d %d",&n,&m) != EOF)
        printf("%d\n",solve(m)-solve(n-1));
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值