hdu 4588 (加法进位次数统计)

来源:互联网 发布:天狼星商品期货软件 编辑:程序博客网 时间:2024/06/11 15:41
Sample Input
1 21 31 41 6
 

Sample Output
0236
题目大意:给两个数a、b,转成二进制,从a + (a+1) + (a+2) + ... + b,一共需要进位多少次。
就是把转换成二进制每一竖行有多少个一记录下来:
举个例子9行吧:
9 8 7 6 5 4 3 2 1
0 0 0 0 0 0 0 0 0   (0)
0 0 0 0 0 0 0 0 1   (1)
0 0 0 0 0 0 0 1 0   (2)
0 0 0 0 0 0 0 1 1   (3)
0 0 0 0 0 0 1 0 0   (4)
0 0 0 0 0 0 1 0 1   (5)
0 0 0 0 0 0 1 1 0   (6)
0 0 0 0 0 0 1 1 1   (7)
0 0 0 0 0 1 0 0 0   (8)
: : :::::::
: : : : : : :  :
就这样会发现规律:
就是第一行就是1和0交替出现,
第二竖行是00 11交替出现,
第三竖行是0000 1111交替出现等等
计算1的个数,然后求需要进位的值....

思路:拆成二进制来看的话,考虑第一位,假设从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/2)(比如00110011001,要把最后的1加回去)。

#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;typedef long long LL ;int a,b ;LL carry,ans ,now ;LL get(int x , int p) {    x++ ; //注意加1 ; 因为从0开始,比如 6 , 他是第7行 ;    LL v = (1LL<< p) ,  num = 0 ; // 1LL<<p ; 表示结果是longlong范围,不然值在int范围。    num = x/v * v /2 ;    x = x % v ;    if(x > (v/2)) num += x - (v/2) ;    return num ;}int main(){    while(~scanf("%d%d",&a,&b))     {           carry = ans = 0 ;           now=1;           while( (1LL<< now) <= b || carry > 0 ) //控制v小于b           {                     carry += get(b,now)-get(a-1,now) ; //第now位1的个数                  ans += carry >> 1 ;                              carry >>= 1 ;                   now++ ;            }           cout << ans << endl ;     }    return 0;}