在[x,y]范围内的整数的二进制补码表示中计数1

时间:2012-04-03 22:27:56

标签: c++ algorithm binary

我的问题与论坛上的上一个问题有关 - Number of 1s in the two's complement binary representations of integers in a range 我没有“添加评论”。所以我在这里问 问题是用2的补码形式计算所有数字的1的数量,它们在两个输入数字指定的范围内 解决方案发布在https://gist.github.com/1285119  如下所示

long long solve(int a)
  {
  if(a == 0) return 0 ;
  if(a % 2 == 0) return solve(a - 1) + __builtin_popcount(a) ;
  return ((long long)a + 1) / 2 + 2 * solve(a / 2) ;
  }


 long long solve(int a,int b)
 {
  if(a >= 0)
  {
   long long ret = solve(b) ;
   if(a > 0) ret -= solve(a - 1) ;
   return ret ;
   }
 long long ret = (32LL * -(long long)a) - solve(~a) ;
 if(b > 0) ret += solve(b) ;
 else if(b < -1)
 {
  b++ ;
  ret -= (32LL * -(long long)b) - solve(~b) ;
 }
return ret ;
}

当输入是 4 //没有测试用例

-1 //第一个数字 -2 //第二个数字 输出0

-1 -3  输出-31

-3 -5 输出-30 // 1的数量如何为-30

1 2 输出2

由于代码在InterviewStreet上发布为Codesprint解决方案,并且在此论坛上有高度评价的答案。这应该是正确的。 任何人都可以解释这条线背后的逻辑 long long ret =(32LL * - (long long)a) - 在solve(int a,int b)中求解(~a) #define INF(int)1e9的目的是什么?不使用时设置无穷大的值?

1 个答案:

答案 0 :(得分:0)

输入结果错误

-1 -2
-1 -3
-3 -5

是因为程序假定两个限制是按升序输入的,并且不进行检查,因此不符合预期的输入会产生错误的结果。一个简单的

if (b < a) {
    int temp = a;
    a = b;
    b = temp;
}
int solve(int a, int b)开头的

会使它以任何顺序返回正确的输入结果。

long long ret = (32LL * -(long long)a) - solve(~a)背后的逻辑是(以二进制补码)n的按位补码为~n = (-n)-1。如果a,则从-132 * |a|的数字中的总位数(0或1)(包括两者)为a < 0。从该计数中,我们减去这些数字中的0位总数,这是其按位补码中的1位总数。这些按位补码是从0到|a| - 1 = ~a的数字,包括两者在内,其中1位的计数由solve(|a| - 1) = solve(~a)给出。