您的位置:首页 > 其它

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

2015-05-11 21:15 501 查看
题目链接: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

2013
ACM-ICPC南京赛区全国邀请赛——题目重现

题意:

给出两个数 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: