您的位置:首页 > 其它

CodeForces - 611B 数学思维

2016-12-10 20:04 417 查看
The year 2015 is almost over.

Limak is a little polar bear. He has recently learnt about the binary system. He noticed that the passing year has exactly one zero in its representation in the binary system — 201510 = 111110111112.
Note that he doesn't care about the number of zeros in the decimal representation.

Limak chose some interval of years. He is going to count all years from this interval that have exactly one zero in the binary representation. Can you do it faster?

Assume that all positive integers are always written without leading zeros.

Input

The only line of the input contains two integers a and b (1 ≤ a ≤ b ≤ 1018) — the first year and
the last year in Limak's interval respectively.

Output

Print one integer – the number of years Limak will count in his chosen interval.

Example

Input
5 10


Output
2


Input
2015 2015


Output
1


Input
100 105


Output
0


Input
72057594000000000 72057595000000000


Output
26


Hint

In the first sample Limak's interval contains numbers 510 = 1012, 610 = 1102, 710 = 1112,810 = 10002, 910 = 10012 and 1010 = 10102.
Two of them (1012 and 1102) have the described property.
题意:就是让你找出给定区间里各个数的二进制中只有一个0的数有多少个;

思路:对于这个题我就单纯的找规律,我们可以发现:

当二进制有两位时 只有1种

当二进制有三位时 只有2种

当四位 3种

五位 4种

由此可以发现这个规律是一个等差数列,那么我们就想可不可以求出给定的区间(a,b)中从(0,a)有多少个,从(0,b]有多少个,两个数做差就为[a,b]的个数;

那么对于给定的数x 他的二进制位数为k,我们找到它二进制中出现第一个0的位置,然后依次将它前面的 1变0将第一个0变为1,就可以找到当二进制位数为k时小于x的满足题意的个数.

这里我来说明一下为什么只需要找到它二进制的第一个0然后变前面不变后面呢?因为我们要求的是区间(0,b]中满足题意的,我们如果变后面的话就会将这个数变大超过b,我们要将这个数变小,就要变高位的1,自己体会一下就明白了;

注意对于区间右面的端点我们需要判断其本身是不是,而左端点不需要;
#include<iostream>

#include<cstdio>

#include<cstring>

#include<cmath>

#define ll long long

using namespace std;

int s1[10000],s2[10000];

ll a,b;

int main()

{ cin>>a>>b;

ll k=0,ans1=0,ans2=0,i,j;

while(a)

{ s1[k++]=a%2;

a>>=1;

}

for(j=k-1;j>=0;j--)

{ if(s1[j]==0)

break;

}

if(k>=3)

{ ans1=((k-1)*(k-2))/2;

}

else

ans1=0;

if(k-j-2>=1&&j>=0)

ans1+=k-j-2;

else if(j<0)

ans1+=k-1;

k=0;

while(b)

{ s2[k++]=b%2;

b>>=1;

}

for(i=k-1;i>=0;i--)

{ if(s2[i]==0)

break;

}

if(k>=3)

{ ans2=((k-1)*(k-2))/2;

}

else

ans2=0;

if(k-i-2>=1&&i>=0)

ans2+=k-i-2;

else if(i<0)

ans2+=k-1;

for(j=0;j<k;j++)

{ if(s2[j]==0)

break;

}

if(j==i)

printf("%lld\n",ans2-ans1+1);

else

printf("%lld\n",ans2-ans1);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm