题目链接: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