source:
题意:统计一段区间的数中二进制表示下0的个数≥1的个数的数有多少个。
思路:数位dp,只是之前的dfs中只需考虑状态和limit边界,而此问题中需要引入前导0的考虑(前导0当然不计入0的个数中),用变量lead表示是否前一位是前导0,用法跟limit一样一样的。
代码如下:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[40];
long long dp[40][80];
long long dfs(int pos,int dif,int lead,int limit)
{
if(pos==-1)
if(dif>=40) return 1;
else return 0;
if(!limit && !lead && dp[pos][dif]!=-1) return dp[pos][dif];
int up=limit?a[pos]:1;
long long ans=0;
for(int i=0;i<=up;i++)
{
if(i==0 && lead) ans+=dfs(pos-1,dif,1,limit&&i==up);
else if(i==0) ans+=dfs(pos-1,dif+1,0,limit&&i==up);
else ans+=dfs(pos-1,dif-1,0,limit&&i==up);
}
if(!limit && !lead) dp[pos][dif]=ans;
return ans;
}
long long f(int x)
{
int i=0;
while(x>0)
{
a[i++]=x%2;
x=x/2;
}
return dfs(i-1,40,1,1);
}
int main()
{
int l,r;
scanf("%d%d",&l,&r);
memset(dp,-1,sizeof(dp));
printf("%lld",f(r)-f(l-1));
return 0;
}