Count The Carries

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 943    Accepted Submission(s): 225


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
 题意:二进制加法也是有进位的,本题给我们两个十进制整数a和b,问我们在二进制加法情况下从a加到b总共进了多少位。

解题思路:由于a,b较大,暴力算法绝对不行。因此我们要找规律,01,10,11,100,101,110,111,若是一起加的话,我们发现在右边第一列上有多少个1,就进位二分之一,之前的每一列先得加上后一列进上来的1再取二分之一,如此我们只需计算出从a到b的每一位上1的总数,这题就引刃而解了。当然计算每一位1的个数,也是有技巧的。技巧就是先计算从0到a与从0到b的各个位上1的总数,之后相减,即a到b的了。

我的代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define I64 ll
#define N 100
void ji(int num[N],int n)
{
 int i;
    for(i=0;i<60;i++) num[i]=0;
    int tmp=2;
    for(i=0;i<60;i++)
    {
     num[i]+=n/tmp*(tmp/2);
     if((n%tmp)>(tmp/2-1)) num[i]+=n%tmp-(tmp/2-1);
     if(tmp>n) break;
     tmp*=2;
    }
}
int sum1[N],sum2[N];
int main()
{
 int i,j,k;
    int a,b;
    while(scanf("%d%d",&a,&b)==2)
    {
        ji(sum1,a-1);
        ji(sum2,b);
        for(i=0;i<60;i++) sum2[i]-=sum1[i];
        __int64 ans=0;
        for(i=0;i<60;i++)
        {
            ans+=sum2[i]/2;
            sum2[i+1]+=sum2[i]/2;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}