码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4588 Count The Carries(数学 二进制 找规律啊)

时间:2015-05-11 21:56:06      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:数学   hdu   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4588


Problem Description
One day, Implus gets interested in binary addition and binary carry. He will transfer all decimal digits to binary digits to make the addition. Not as clever as Gauss, to make the addition from a to b, he will add them one by one from a to b in order. For example, from 1 to 3 (decimal digit), he will firstly calculate 01 (1)+10 (2), get 11,then calculate 11+11 (3),lastly 110 (binary digit), we can find that in the total process, only 2 binary carries happen. He wants to find out that quickly. Given a and b in decimal, we transfer into binary digits and use Implus‘s addition algorithm, how many carries are there?
 

Input
Two integers a, b(0<=a<=b<1000000000), about 100000 cases, end with EOF.
 

Output
One answer per line.
 

Sample Input
1 2 1 3 1 4 1 6
 

Sample Output
0 2 3 6
 

Source


题意:

给出两个数 a 和 b ,从 a 一直加到 b,求在二进制的情况下,一共发生了多少次进位。

PS:

依次相加可以转换为先所有的数一起相加,然后从低到高统一进位。

这样只需统计 a ~ b 之间每一位有多少个1就好了。

从而转换成 0  ~ b 中每位有多少个1, 

0~b - 0~(a-1)得a~b.

从图中我们可以看出(也可以自己模拟一下)第 i 位的 0 , 1 周期为 2 ^ i,而且 0 和 1 的个数各占一半为:2 ^(i-1);

技术分享


代码如下:

#include <cstdio>
#include <cstring>
#define LL long long

LL er[47];
LL ca[47], cb[47];

void init()
{
    er[0] = 1;
    for (int i = 1; i <= 32; i++)//2的次方
    {
        er[i] = er[i-1] * 2;
    }
        
}
void cal(LL x, LL* a)
{
    if(x <= 0)
        return;
    LL ans = 0, s = 0;

    for(int i = 1; i <= 32; i++)
    {
        LL t = er[i];//周期为2^i
        LL c = x/t;//有多少个周期
        LL d = x%t+1;//不足一个周期的数,+1:加上零所占的位

        a[i] = c * er[i-1];//统计1的个数

        if(d > er[i-1])//是否还有剩余的1
        {
            a[i] += d - er[i-1];
        }
    }
}

int main ()
{

    init();
    LL a, b;
    while(~scanf("%lld%lld",&a,&b))
    {
        memset(ca, 0, sizeof(ca));
        memset(cb, 0, sizeof(cb));
        cal(b, cb);
        cal(a-1, ca);

        LL ans = 0, s = 0;
        //0~b - 0~(a-1) 即为 a ~ b
        for (int i = 0; i <= 32; i++) //从低到高一次进位
        {
            s += cb[i] - ca[i];
            s /= 2;
            ans += s;
        }
        while(s)//如果最高位依次向前进位
        {
            s /= 2;
            ans += s;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


HDU 4588 Count The Carries(数学 二进制 找规律啊)

标签:数学   hdu   

原文地址:http://blog.csdn.net/u012860063/article/details/45648905

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!