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 }