题意:
求以内有多少个数的二进制位里的数量大于的数量,数据范围。
思路:
把转为二进制,记忆化搜索二进制数,(写数位一定要看清参数,参数写反把自己搞蒙了,血亏)。
二进制的前导零是无效的,当前的长度、出现的次数以及出现的次数三个状态才能保证结果一样(写这么多题了我居然没加出现的次数这个状态)
Code:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include <vector> #include<map> #include<set> #include<utility> using namespace std; typedef long long ll; const int maxn = 1e5+7,maxm=2e5+7; inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } ll dp[35][35][35]; int digit[35]; ll dfs(int len,int cnt0,int cnt1,bool check,bool limit) { if(!len) { return cnt0>=cnt1; } if(!limit&&dp[len][cnt0][cnt1]!=-1) return dp[len][cnt0][cnt1]; int endi=(limit?digit[len]:1); ll ans=dfs(len-1,cnt0+1*check,cnt1,check,limit&&0==endi); if(endi==1) ans+=dfs(len-1,cnt0,cnt1+1,true,limit); if(!limit) dp[len][cnt0][cnt1]=ans; return ans; } ll solve(ll x) { int len=0; while(x) { digit[++len]=x&1; x>>=1; } return dfs(len,0,0,false,true); } int main() { ll l,r; memset(dp,-1,sizeof dp); while(~scanf("%lld%lld",&l,&r)) { printf("%lld\n",solve(r)-solve(l-1)); } return 0; }