njust 1739 - Count The Carries


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


你可能感兴趣的:(c,ACM)