Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 计数在整数范围内设置每个位的次数_Algorithm_Bit Manipulation - Fatal编程技术网

Algorithm 计数在整数范围内设置每个位的次数

Algorithm 计数在整数范围内设置每个位的次数,algorithm,bit-manipulation,Algorithm,Bit Manipulation,给定从M到N的整数范围,其中 M和N可能不是2的幂。有没有 一种有效的方法来计算每次的次数 位设置好了吗 例如,范围为0到10 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001 10 1010 我希望在每列中设置每个位的时间计数,在这种情况下为3,4,5,5。每个位级别都有一个模式,由2^power0s和2^power1s组成 因此有三种情况: 当M和N是M=0模

给定从M到N的整数范围,其中 M和N可能不是2的幂。有没有 一种有效的方法来计算每次的次数 位设置好了吗

例如,范围为0到10

0   0000
1   0001
2   0010
3   0011
4   0100
5   0101
6   0110
7   0111
8   1000
9   1001
10  1010

我希望在每列中设置每个位的时间计数,在这种情况下为3,4,5,5。

每个位级别都有一个模式,由
2^power
0s和
2^power
1s组成

因此有三种情况:

  • M
    N
    M=0模2^(幂+1)
    N=2^(幂+1)-1模2^(幂+1)
    时。在这种情况下,答案只是
    (N-M+1)/2

  • M
    N
    为整数除以
    2^(幂+1)
    时,M和N=相同的数字。在这种情况下,有几个子类别:

  • M
    N
    都是这样的:当整数除以
    2^(幂)
    时,
    M
    N
    =相同的数字。在这种情况下,如果
    N<2^(power)mod 2^(power+1)
    ,则答案为
    0
    ,否则答案为
    N-M+1
  • 否则它们是不同的,在这种情况下答案是
    N-(N/2^(power+1))*2^(power+1)+2**(power)
    (整数除法),如果
    N>2^(power)mod 2^(power+1)
    ,否则答案是
    (M/2^(power+1))*2^(power+1)-1-M
  • 最后一种情况是,当整数除以
    2^(幂+1)
    时,M和N=不同的数字。在这种情况下,您可以将1和2的技术结合起来。查找
    M
    (M/(2^(幂+1))+1)*(2^(幂+1))-1之间的数字数。然后在
    (M/(2^(power+1))+1)*(2^(power+1))
    (N/(2^(power+1)))*2^(power+1)-1之间。最后在
    (N/(2^(power+1))*2^(power+1)
    N
    之间

  • 如果这个答案有逻辑错误,让我知道,它是复杂的,我可能有点搞砸了

    更新:

    python实现

    def case1(M, N):
      return (N - M + 1) // 2
    
    def case2(M, N, power):
      if (M > N):
        return 0
      if (M // 2**(power) == N // 2**(power)):
        if (N % 2**(power+1) < 2**(power)):
          return 0
        else:
          return N - M + 1
      else:
        if (N % 2**(power+1) >= 2**(power)):
          return N - (getNextLower(N,power+1) + 2**(power)) + 1
        else:
          return getNextHigher(M, power+1) - M
    
    
    def case3(M, N, power):
      return case2(M, getNextHigher(M, power+1) - 1, power) + case1(getNextHigher(M, power+1), getNextLower(N, power+1)-1) + case2(getNextLower(N, power+1), N, power)
    
    def getNextLower(M, power):
      return (M // 2**(power))*2**(power)
    
    def getNextHigher(M, power):
      return (M // 2**(power) + 1)*2**(power)
    
    def numSetBits(M, N, power):
      if (M % 2**(power+1) == 0 and N % 2**(power+1) == 2**(power+1)-1):
        return case1(M,N)
      if (M // 2**(power+1) == N // 2**(power+1)):
        return case2(M,N,power)
      else:
        return case3(M,N,power)
    
    if (__name__ == "__main__"):
      print numSetBits(0,10,0)
      print numSetBits(0,10,1)
      print numSetBits(0,10,2)
      print numSetBits(0,10,3)
      print numSetBits(0,10,4)
      print numSetBits(5,18,0)
      print numSetBits(5,18,1)
      print numSetBits(5,18,2)
      print numSetBits(5,18,3)
      print numSetBits(5,18,4)
    
    def案例1(M,N):
    返回(N-M+1)//2
    def箱2(M、N、电源):
    如果(M>N):
    返回0
    如果(M//2**(功率)==N//2**(功率)):
    如果(N%2**(功率+1)<2**(功率)):
    返回0
    其他:
    返回N-M+1
    其他:
    如果(N%2**(功率+1)>=2**(功率)):
    返回N-(getNextLower(N,power+1)+2**(power))+1
    其他:
    返回getNextHigher(M,power+1)-M
    def壳体3(M、N、电源):
    返回case2(M,getNextHigher(M,power+1)-1,power)+case1(getNextHigher(M,power+1),getNextLower(N,power+1)-1)+case2(getNextLower(N,power+1),N,power)
    def getNextLower(M,功率):
    返回(M//2**(功率))*2**(功率)
    def getNextHigher(M,电源):
    返回(M//2**(功率)+1)*2**(功率)
    def数值(M、N、功率):
    如果(M%2**(功率+1)==0和N%2**(功率+1)==2**(功率+1)-1):
    返回案例1(M,N)
    如果(M//2**(幂+1)=N//2**(幂+1)):
    返回壳体2(M、N、电源)
    其他:
    返回壳体3(M、N、电源)
    如果(\uuuuu name\uuuuuu==“\uuuuuu main\uuuuuu”):
    打印数字位(0,10,0)
    打印数字位(0,10,1)
    打印数字位(0,10,2)
    打印数字位(0,10,3)
    打印数字位(0,10,4)
    打印数字位(5,18,0)
    打印数字位(5,18,1)
    打印数字位(5,18,2)
    打印数字位(5,18,3)
    打印数字位(5,18,4)
    
    它可以像-

    取x1=0001(用于在最右边的列中查找1),x2=0010,x3=0100,依此类推

    现在,在一个循环中-

    n1 = n2 = n3 = 0
    for i=m to n:
        n1 = n1 + (i & x1)
        n2 = n2 + (i & x2)
        n3 = n3 + (i & x3)
    
    在哪里-
    ni=第i列中的1个数(从右起)

    这可能是最慢的方式,仍然有意义。这就是为什么我说它是最简单的,而不是最好的:)可能可以做一些简化,但我将把它作为练习留给读者。