[poj3252]Round Numbers(数位dp)

题意:求出区间内二进制表示是0的个数不小于1的个数的数的个数。

解题关键:数位dp,记忆化搜索的写法。

如果设一个三维数组,则不需要!lead。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;  
int dp[35][66];  
int a[35];

int dfs(int pos,int sta,bool lead,bool limit){
    if(pos==-1)  return sta>=32;  
    if(!limit&&!lead&&dp[pos][sta]!=-1) return dp[pos][sta];
    int up=limit?a[pos]:1,ans=0;
    for(int i=0;i<=up;i++){
        int t=lead&&i==0;
        ans+=dfs(pos-1,t?sta:sta+(i==0?1:-1),t,limit&&i==a[pos]); 
    }
    if(!limit&&!lead) dp[pos][sta]=ans;  //!lead?
    return ans;
}

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

int main(){
    memset(dp,-1,sizeof dp);  
    int a,b;
    while(~scanf("%d%d",&a,&b)){
        printf("%d\n",solve(b)-solve(a-1));
    }
    return 0;
}

 

posted @ 2017-11-05 22:41  Elpsywk  阅读(149)  评论(0编辑  收藏  举报