题目大意:前一个区间里二进制表示状态下0的个数不小于1的个数的数的个数;
题目解析:定义dp[i][j]表示在i位上0个个数和1的个数的差值的个数,因为会产生负值所以临界值可以设置为32,这道题前导0会有影响,所以需要特别考虑;
AC代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> using namespace std; int dp[40][65],n,m,num[40]; int dfs(int pos,int sum,bool lead,bool limit) { if(pos==-1) return sum>=32; if(!limit&&!lead&&dp[pos][sum]!=-1) return dp[pos][sum]; int u=limit?num[pos]:1; int ans=0; for(int i=0;i<=u;i++) { if(lead&&i==0) ans+=dfs(pos-1,sum,lead,limit&&i==num[pos]); else ans+=dfs(pos-1,sum+(i==0?1:-1),lead&&i==0,limit&&i==num[pos]); } if(!limit&&!lead) return dp[pos][sum]=ans; return ans; } int cal(int x) { int pos=0; while(x) { num[pos++]=x&1; x>>=1; } return dfs(pos-1,32,true,true); } int main() { memset(dp,-1,sizeof(dp)); while(scanf("%d%d",&n,&m)!=EOF) { printf("%d\n",cal(m)-cal(n-1)); } }