题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4588
1 2 1 3 1 4 1 6
0 2 3 6
题意:
给出两个数 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(数学 二进制 找规律啊)
原文地址:http://blog.csdn.net/u012860063/article/details/45648905