HDU 4588 Count The Carries(数学统计)

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.

 

题目大意:给两个数a、b,转成二进制,从a + (a+1) + (a+2) + ... + b,一共需要进位多少次。

思路:拆成二进制来看的话,考虑第一位,假设从1~b有x1个数的第一位是1,从1~a-1有x2个数的第一位是1,那么从a~b就有(x1-x2)个数第一位是1,那么在第一位需要进位的次数就为(x1-x2)/2。假设从a~b有x3个数第二位是1,那么在第二位需要进位的次数就为((x1-x2)/2 + x3)/2。以此类推。

至于算1~x有多少个第p位是1的方法,我做的比较奇葩……比如第二位,从1~x都是重复001100110011……那么就会有x/4个0011,总共就有x/4*4/2个1……之后看x%4之后还有多少个数,如果大于4的一半,就加上x%4-4(比如00110011001,要把最后的1加回去)。

PS:前面的除号都是整除。所以那个除了又乘是不能约掉的。

 

代码(1140MS):

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 int a, b;
 9 LL ans, carry, now;
10 
11 inline LL get(LL x, int p) {
12     ++x;
13     LL v = 1LL << p, ret = 0;
14     ret += x / v * v / 2;
15     x %= v;
16     if(x > v / 2) ret += x - v / 2;
17     return ret;
18 }
19 
20 int main() {
21     //while(cin>>a>>b) cout<<get(a, b)<<endl;
22     while(scanf("%d%d", &a, &b) != EOF) {
23         carry = ans = 0;
24         now = 1;
25         while(1LL<<now <= b || carry > 0) {
26             carry += get(b, now) - get(a - 1, now);
27             ans += carry >> 1;
28             carry >>= 1;
29             ++now;
30         }
31         cout<<ans<<endl;
32     }
33 }
View Code

 

posted @ 2013-08-24 18:01  Oyking  阅读(370)  评论(0编辑  收藏  举报