include[HTML_REMOVED]
using namespace std;
typedef long long ll;
ll a,b;
int main()
{
//使用枚举的方法进行处理
//开始时想用暴力循环的方法这样的话就会爆时间
//思考一下10的18次方就是longlong类型,0的位置只有63种可能性(去掉0在头部的可能性)
cin>>a>>b;
int res=0;
//开始枚举
for(int i=0;i<=63;i++)//这里表示0的位置
{
for(int j=0;j<=i-2;j++)//表示0的右边最多有多少个1
{
int r=j,l=i-j-1;
//计算
ll left=(1ll<<l)-1;//惯例,表示2的某次方从1到这个某次方的所有数字
ll right=(1ll<<r)-1;
ll num=(left<<j+1)+right;
if(num>=a&&num<=b) res++;
}
}
cout<<res;
return 0;
}
使用暴力的方法会超时的,考虑到了不好求0的个数用1反推是很好的,但是没想到要使用枚举的方法进行处理,因此要注意有限的个数可以使用枚举的方法尝试处理。
要注意的点:
1、10的18次方意思就是2的64次就是long long的数据类型
本题枚举的方法
1、0只有一个位置可以是2的64次方中的除了第64位这个前置0的任何位置;
2、放好了0就考虑1的位置,枚举1的右边有多少个1;
3、然后使用位移的手段进行计算