POJ 3252 区间内一个数的二进制中0的数量要不能少于1的数量(数位DP)

题意:求区间内二进制中0的数量要不能少于1的数量

 

分析:很明显的是数位DP;

菜鸟me : 整体上是和数位dp模板差不多的 , 需要注意的是这里有前导零的影响 , 所以需要在dfs()里面增加zor 变量的限制条件 , 

那么我们的dp[i][j] 是表示第i 位置 , ,0的数量减去1的数量不少于 j 的方案数 , 那剩下的就简单了咯 ,哦还需要注意的是 这里的 j 会出现负数的情况 , 那也很好解决咯 ,偏移下就好拉 , 从32开始 ,也就是说32表示0

 

#include<stdio.h>
#include<string.h>
int dp[40][70];
int a[70];
int dfs(int pos , int sta , int limit , int zor)
{
    if(pos==-1)
    return sta>=32;
    if(!limit && !zor && dp[pos][sta]!=-1)
    return dp[pos][sta];
    int up=limit?a[pos]:1;
    int ans=0;
    for(int i=0 ; i<=up ; i++)
    {
        if(zor && i==0)
        ans+=dfs(pos-1,sta,limit&&i==a[pos],zor&&i==0);
        else
        {
            if(i==0)
            ans+=dfs(pos-1,sta+1,limit&&i==a[pos],zor&&i==0);
            else
            ans+=dfs(pos-1,sta-1,limit&&i==a[pos],zor&&i==0);
        }

    }
    if(!limit && !zor)
    dp[pos][sta]=ans;
    return ans;
}
int so(int x)
{
    int ans=0;
    while(x)
    {
        a[ans++]=x%2;
        x/=2;
    }
    return dfs(ans-1,32,1,1);
}
int main( )
{
    int l,r;
    memset(dp,-1,sizeof(dp));
    while(scanf("%d%d",&l,&r)!=EOF)
    {
        printf("%d\n",so(r)-so(l-1));
    }
    return 0;
}
View Code

 

posted @ 2018-11-06 22:28  shuai_hui  阅读(290)  评论(0编辑  收藏  举报