c_cpp 总数没有。 A和B之间的2的补码表示中的1,包括在内。 Hackerrank的“2补”问题。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 总数没有。 A和B之间的2的补码表示中的1,包括在内。 Hackerrank的“2补”问题。相关的知识,希望对你有一定的参考价值。

#include <stdio.h>
#include <math.h>
#include <limits.h>
 
unsigned int prevTwo(unsigned int x) // bit twiddling
{
  unsigned int y = x;
  x--;
  x |= x >> 1;
  x |= x >> 2;
  x |= x >> 4;
  x |= x >> 8;
  x |= x >> 16;
  x++;
  if(x != y)
    x = x >> 1;
  return x;
}
 
long long countOneZero(int n)
{
  if(n == 0 || n == 1)
    return n;
  int k = prevTwo((unsigned int)n);
  int p = 1, k2 = k;
  while((k>>1) != 1)
    {
      k = k>>1;
      p++;
    }
  return (long long)pow((double)2, p-1)*p + (n-k2+1) + countOneZero(n-k2);
}
 
long long countOnes(int a, int b)
{
  if(a <= 0)
    a = 1;
  return countOneZero(b) - countOneZero(a-1);
}
 
int main()
{
  int a, b, flag;
  int t, T;
  scanf("%d",&T);
  for(t=0;t<T;t++)
    {
      flag = 0;
  scanf("%d %d", &a, &b);
  if(a == 0 && b == 0)
    {
      printf("%d\n",0);
      continue;
    }
  if(a == 0)
    a++;
  if(b == 0)
    b--;
  if(a == INT_MIN && b == INT_MIN)
    {
      printf("%d\n",1);
      continue;
    }
  if(a == INT_MIN)
    {
      flag = 1;
      a++;
    }
  if(a < 0 && b < 0)
    {
      a = -a;
      b = -b;
      printf("%lld\n",(long long)32*(a-b+1)-countOnes(b-1,a-1) + flag);
    }
  else if(a > 0 && b > 0)
    {
      printf("%lld\n",countOnes(a,b));
    }
  else 
    {
      a = -a;
      printf("%lld\n",(long long)32*a-countOnes(1,a-1)+countOnes(1,b) + flag);
    }
    }
  return 0;
}

以上是关于c_cpp 总数没有。 A和B之间的2的补码表示中的1,包括在内。 Hackerrank的“2补”问题。的主要内容,如果未能解决你的问题,请参考以下文章

数据的表示和运算-第二节2:补码加减运算器和标志位的生成

Q 格式使用总结

原码反码补码移码之间的关系和转换

C_基础编码(补码详解)

补码如何理解

(计算机组成原理)第二章数据的表示和运算-第二节1:定点数的表示(原码反码补码和移码)