比赛的时候没有做出来,和大家讨论一下原来是统计一的数量,就可以了。我就想着先算0 到a-1的进位,数再算0-b的进位数然后后者减前者就是了,测试了一下错误,改成0到a的还是错误,看来这个想法不对。还是老老实实地统计了一遍[a,b]的1的个数。就过了。统计的时候我是每一位的去统计,然后用0到b 的1的个数减去,0到a-1的1的个数。
在统计1的个数的时候。我用的是一种打包的思想最后一位是0,1交替变化,前一位是0,0,1,1变化,这样就把2^n (n = 0.1.2.3....)个相同的数,如1或0分别的看成一个0或1包这样统计包的个数这样可以递归求解了,我是用循环实现实现的。
#include <stdio.h>
//long long int num(int a,int b)
//{
//悲催的代码
// long long ans = 0;
// int p_tmp = 0;
// int packet = 1;
// int carri_tmp = 0,one_num_tmp = 0;
// while(a >= packet){
// p_tmp = (a+1)/ packet;
// one_num_tmp = 0;
//
// if(p_tmp %2 == 1)
// one_num_tmp = a + 1 - p_tmp *packet;
//
// //p_tmp = p_tmp /2
//
// one_num_tmp += (p_tmp / 2) * packet + carri_tmp;
//
// carri_tmp = one_num_tmp/2;
//
// ans += carri_tmp;
//
// packet *= 2;
// }
// while(carri_tmp > 1)
// {
// carri_tmp /= 2;
// ans += carri_tmp;
// }
// return ans;
//}
long long int one(long long int a,long long int packet_base)
{
//0...a-1
long long int packet = a/packet_base;
long long int ans = 0;
if(packet%2)
ans += a - packet * packet_base;
ans += packet/2 * packet_base;
return ans;
}
long long int num(long long int a,long long int b)
{
long long int packet_base = 1;
long long int one_num_a,one_num_b,one_num;
long long int carri = 0,ans = 0;
while(packet_base <= b)
{
one_num_a = 0;
if(packet_base <= a){
one_num_a = one(a,packet_base);
}
one_num_b = one(b+1,packet_base);
one_num = one_num_b - one_num_a + carri;
carri = one_num / 2;
ans += carri;
packet_base *= 2;
}
while(carri >1)
{
carri /= 2;
ans += carri;
}
return ans;
}
int main()
{
long long int a,b;
while(~scanf("%lld%lld",&a,&b))
//while(scanf("%d",&a),a)
{
printf("%lld\n",num(a,b));
}
return 0;
}