比赛的时候没有做出来,和大家讨论一下原来是统计一的数量,就可以了。我就想着先算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; }