HDU-4588 Count The Carries (模拟)

来源:互联网 发布:java业余培训 编辑:程序博客网 时间:2024/05/22 07:39

Count The Carries

http://acm.hdu.edu.cn/showproblem.php?pid=4588
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)


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 21 31 41 6
 

Sample Output
0236

题目大意:给定两个十进制数a和b,求在二进制下,从a加到b的进位数?

看到数据范围就反应到不能直接模拟计算,又想到以前类似这种范围特别大的题目都是按位处理,就反应过来可以统计每一位中1的个数,直接算出当前位的进位数

写了前几位的数就能发现每一位上1的个数的分布是有规律的:

0:0000

1:0001

2:0010

3:0011

4:0100

5:0101

6:0110

7:0111

8:1000

在最前面添加一个0就能很容易的求出0~n中每一位上1的个数

规律如下:

从右开始数的第i位上,每2^i个数是一个循环,其中1的个数占每个循环的后2^(i-1)个

然后就能很容易的写出算法

#include <cstdio>using namespace std;int a,b,pre,tmp,rem;//pre表示上一位的进位long long ans;int cal(int x,int i) {//统计1~x-1中,从右数的第i+1位上1的个数    if(i>=31)//由于10^9<2^30,所以从右数的第31位及后面的位上1的个数均为0        return 0;    tmp=x/(1<<i)*(1<<(i-1));    rem=x%(1<<i);    if(rem>(1<<(i-1)))        tmp+=rem-(1<<(i-1));    return tmp;}int main() {    while(2==scanf("%d%d",&a,&b)) {        pre=ans=0;        for(int i=1;i<63;++i) {//由于某一位产生的进位可能会连续进多位,所以不能只处理到第30位            pre=(cal(b+1,i)-cal(a,i)+pre)>>1;            ans+=pre;        }        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击