题意:定义一种数,满足条件:二进制表示中0个数大于等于1的个数。求给定闭区间内有多少个这种数。
思路:数位DP,dp[pos][zero][one] 表示已知二进制中首位1在第one位上,目前有零个数zero,现在要考虑pos位置上放0或1的满足条件的数的个数。记忆化搜一下就好了。
代码:
/*
First数位DP POJ 3252
*/
#include<string.h>
#include<stdio.h>
int dp[33][33][33];
char buf[33];
int dfs(int zero,int one,int pos,int flag)
{
int ans=0;
if(zero!=-1 && !flag && dp[pos][zero][one]!=-1)
return dp[pos][zero][one];
if(pos==0)
return one-zero<=zero;
int end=flag?buf[pos-1]:1;
for(int i=0;i<=end;i++){
if(i==1 && !one)
ans+=dfs(pos-1,pos,pos-1,flag && i==end);
else
ans+=dfs(zero-i,one,pos-1,flag && i==end);
}
if(one && !flag){
dp[pos][zero][one]=ans;
}
return ans;
}
inline int change(int x,char buf[],int r)
{
int i=0;
while(x){
buf[i++]=x%2;
x/=2;
}
return i;
}
inline int f(int x)
{
int one=0,zero=0,n;
if(x==0) return 0;
n=change(x,buf,2);
return dfs(-1,0,n,1);
}
int main()
{
int l,r;
memset(dp,-1,sizeof(dp));
while(~scanf("%d %d",&l,&r)){
printf("%d\n",f(r)-f(l-1));
}
return 0;
}