简体   繁体   English

如何查找给定范围内的整数数甚至设置了位

[英]How to find number of integers in a given range has even set bits

I want to know how many numbers say x, in a given range lets say l and r, l < r, present where number of 1's in binary representation of x is even. 我想知道在给定范围内有多少个数字说x,可以说l和r,l <r,其中x的二进制表示形式中1的个数是偶数。 Is there any efficient way to find that? 有什么有效的方法可以找到吗?

Here's a key fact: 这是一个关键事实:

  • If n is a non-negative even number, then exactly half of the non-negative integers less than n have even parity and the other half have odd parity. 如果n是非负偶数 ,则小于n的非负整数中恰好有一半具有偶数奇偶校验,而另一半则具有奇数奇偶校验。 ("Even parity" means that the number of bits in the binary representation is even.) (“偶校验”表示二进制表示中的位数是偶数。)

Suppose we need to count the number of integers in the range [ l , r ) with some property P , and we know how to solve this problem for any range where l is 0. ( "[ l , r )" is a "half-open range": all integers n where ln < r . 假设我们需要计数的一些属性P的范围[L,R)的整数数量,我们知道如何解决这个问题的任何范围,其中l0(“[L,R)”是一个“半-open范围“:所有整数n其中L≤ñ<R。 That makes the arithmetic easier.) Then we just need to subtract in order to solve the general problem where l ≠0: COUNT[ l , r ) = COUNT[0, r ) − COUNT[0, l ). 然后,我们只需减去即可解决l ≠0的一般问题:COUNT [ lr )= COUNT [0, r )-COUNT [0, l )。

The first fact doesn't quite tell us all we need to know, since it only works for even n . 第一个事实并不能完全告诉我们我们需要知道的所有信息,因为它仅适用于n But if n is odd, n-1 is even, and all we need to do is check the parity of n-1 itself, which is the extra number not in the range [0, n -1). 但是,如果n为奇数, n-1为偶数,而我们要做的就是检查n-1本身的奇偶校验,这是不在[0, n -1)范围内的额外数字。

Putting all that together, if we have the range [ l , r ), we compute the count as follows: 将所有内容放在一起,如果我们有范围[ lr ),我们将按以下方式计算计数:

  • COUNT(0, l ) is l /2 if l is even, and ( l -1)/2+PARITY( l ) if l is odd COUNT(0,1)L / 2如果L为偶数,和(l-1)/ 2 + PARITY( )如果L为奇数
  • COUNT(0, r ) is r /2 if r is even, and ( r -1)/2+PARITY( r ) if r is odd COUNT(0,r)R / 2如果r是偶数,和(R-1)/ 2 + PARITY(R)如果r是奇数
  • COUNT( l , r ) is COUNT(0, r ) − COUNT(0, l ) COUNT( lr )是COUNT(0, r )− COUNT(0, l

That last computation requires at most two parity computations, regardless of how large the range is, as well as a couple of divisions and a subtraction. 最后一个计算最多需要两个奇偶校验计算,而不管范围有多大,还要进行两次除法和减法。

If this were a mathematics site, I might feel compelled to prove the assertion in the key fact at the beginning, but since this is CS I will content myself with a proof outline. 如果这是一个数学站点,那么一开始我可能会被迫证明关键事实中的断言,但是由于这是CS,因此我将对证明大纲感到满意。 We first note that if i is even, then PARITY( i ) and PARITY( i +1) are different (since the binary representations only differ in the last bit). 我们首先注意到,如果i为偶数,则PARITY( i )和PARITY( i +1)是不同的(因为二进制表示形式的最后一位不同)。 Conversely, if i is odd, then PARITY( i ) and PARITY( i -1) are different. 相反,如果i为奇数,则PARITY( i )和PARITY( i -1)不同。 Now, take all the integers in [0, n ) and divide them into the set of integers with odd parity and the set with even parity, and consider the homomorphism 现在,取[0, n )中的所有整数并将它们分为具有奇校验的整数集和具有偶校验的整数集,并考虑同构

f ( i )⇒ i +1 if i is even; F(1)⇒ 1如果i是偶数;
f ( i )⇒ i −1 if i is odd; F(1)⇒ -1,如果i是奇数;

The image of f over one of the two subsets of [0, n ) is the other subset, since the parity of f ( i ) is different from the parity of i . 在[0, n )的两个子集之一上的f的图像是另一个子集,因为fi )的奇偶性不同于i的奇偶性。 So the two subsets are the same size. 因此,两个子集的大小相同。

Assuming that your range falls in positive integer domain, I wrote the following C++ code 假设您的范围属于正整数域,我编写了以下C ++代码

#include <iostream> 
#include <cmath> 
using namespace std;

int find_even_bits_helper(int upper, int level, bool sign) {
    // find even-bit number starting from 0
    // level and sign just for printing purpose 
    for (int i = 0; i <= level; ++i) cout << ' ';
    cout << "[0," << upper << "] -> " << '\n';
    int answer;
    if (upper == -1) {
        answer = 0;
    }
    else if (upper == 0) {
        answer = 1;
    }
    else if ((upper & (upper + 1)) == 0) {
        answer = (upper + 1) / 2;
    }
    else {
        int threshold = pow(2, floor(log2(upper)));
        int base_part = find_even_bits_helper(threshold - 1, level + 1, sign);
        int extra_part = (upper - threshold + 1) \
                       - find_even_bits_helper(upper - threshold, level + 1, !sign);
        // Essentially remove the highest 1 bit, thus all odd-bit becomes even-bit 
        answer = base_part + extra_part;
    }
    for (int i = 0; i <= level; ++i) cout << ' ';
    if (sign) cout << "+";
    else cout << "-";
    cout << answer << '\n';
    return answer;
}

int find_even_bits(int lower, int upper) {
    return find_even_bits_helper(upper, 0, true) \
         - find_even_bits_helper(lower - 1, 0, false);
}

int main() {
    cout << "Result is: " << find_even_bits(7,34) << '\n';
}

Testing range [7, 34] outputs: 测试范围[7,34]输出:

 [0,34] ->
  [0,31] ->
  +16
  [0,2] ->
   [0,1] ->
   -1
   [0,0] ->
   +1
  -1
 +18
 [0,6] ->
  [0,3] ->
  -2
  [0,2] ->
   [0,1] ->
   +1
   [0,0] ->
   -1
  +1
 -4
Result is: 14

It shows that [0, 34] has 18 even-bit integers and [0, 6] has 4 even-bit integers. 它显示[0,34]具有18个偶数位整数,[0,6]具有4个偶数位整数。

Therefore, the answer is 18 - 4 = 14 . 因此,答案是18 - 4 = 14

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何找到给定范围内除以给定数字时具有一定余数的值的数量? - How to find the number of values in a given range that has a certain remainder when divided by a given number? 确定BITS的总和 - sum of BITS is given find thar number 计数 2 个给定数字的设置位总数 - Count Total number of set bits for 2 given numbers 给定偶数个顶点,如何根据邻近度找到最佳对? - Given an even number of vertices, how to find an optimum set of pairs based on proximity? C++ 你如何在 N 个整数中找到一个具有最相似位的数字? - C++ how would you find a number with the most similar bits in N integers? 查找使用2个设置位形成的第n个数字 - Find the nth number formed using 2 set bits 如何提取给定数字的 p MSB 位 - How to extract the p MSB bits of a given number 给定一个 integer N&gt;0,区间 [0, 2^N) 中有多少个整数正好有 N-1 个设置位? 写一个返回正确答案的简短 function - Given a integer N>0, how many integers in the interval [0, 2^N) have exactly N-1 set bits? Write a short function that returns the correct answer 如何找到给定数字的频率进入数组的范围? - How do I find the frequency of a given number into a range into an array? 如何在std :: set &lt;对中找到最大值 <int, int> &gt;在给定范围内? - How to find the maximum in std::set< pair<int, int> > in a given range?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM