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;
}