Count The Carries

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=4588

题意:给你 a,b两个数,然后让a到b之间的数做2进制的加法,问你与多少次进位。例如:1,3,1+2+3=01+10+11=110,共有2次进位。

题解:这一题,如果直接暴力求解的话,肯定不行,数据很大。所以得转变思路,很容易想到,统计a到b每一位的1的个数,例如:1--3,01,10,11,右起第一位是2,往左是

2,所以一共有2/2+(2+1)/2=2种,所以结果是2. 接下来的问题就是如何统计每一位1的个数。110*110,对于*,如果*是1,那么从0到110*110,这一位就有(110)*2^3+(110+1),如果是*是0,则这一位有110*2^3,每一位一次类推,即可得到每一位1的个数,计算0--a-1,然后计算0-b,然后二者相剪,即可得到a到b之间的数据

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 int ans1[60];
 8 int ans2[60];
 9 int temp[60];
10 int a;
11 int b;
12 void solve(int x){
13    int counts=1;
14    int s=x;
15    memset(temp,0,sizeof(temp));
16    while(s){
17         temp[counts]=s&1;
18         s/=2;
19       counts++;
20    }
21    counts--;
22    for(int k=counts;k>=1;k--){
23         int sum1=0,sum2=0;
24         int ct=1;
25        for(int j=k+1;j<=counts;j++){
26            sum1+=ct*temp[j];
27            ct*=2;
28        }
29         ct=1;
30         for(int j=1;j<k;j++){
31             sum2+=ct*temp[j];
32             ct*=2;
33         }
34         if(temp[k]==1)
35             ans1[k]=sum1*(1<<(k-1))+(sum2+1);
36         else
37             ans1[k]=sum1*(1<<(k-1));
38    }
39 }
40 int main(){
41      while(~scanf("%d%d",&a,&b)){
42         memset(ans1,0,sizeof(ans1));
43         memset(ans2,0,sizeof(ans2));
44         solve(a-1);
45         for(int i=1;i<=49;i++){
46             ans2[i]=ans1[i];
47         }
48          memset(ans1,0,sizeof(ans1));
49         solve(b);
50         for(int i=1;i<=49;i++){
51             ans1[i]-=ans2[i];
52         }
53          int st=0;
54          for(int i=1;i<=49;i++){
55             st+=ans1[i]/2;
56             ans1[i+1]+=ans1[i]/2;
57          }
58          printf("%d\n",st);
59      }
60 }
View Code

 

posted on 2014-04-16 16:42  天依蓝  阅读(165)  评论(0编辑  收藏  举报

导航