puzzle contents
Contents
raw puzzle

Original Problem

Given a long integer nn, count the number of values of kk satisfying the following conditions:

where nn and kk are long integers and \oplus is the bitwise XOR operator.

You are given qq queries, and each query is in the form of a long integer denoting nn. For each query, print the total number of values of satisfying the conditions above on a new line.

For example, you are given the value n=5n=5. Condition 22 requires k<nk<n The following tests are run:

We find that there are 22 values meeting the first condition: 22 and 33.

Function Description

Complete the theGreatXor function in the editor below. It should return an integer that represents the number of values satisfying the constraints.

Constraints

Solution

We need to count all numbers whose XOR with nn produces a greater value. The definition of the bitwise XOR is, that the resulting bit is always 1 if the bit at the same position in both variables are different. To get a feeling of how the XOR operation affects the numbers, lets have a look at the first values of nn in binary notation:

kknnknk\oplus n
011011
011110
101101
001100101
010100110
011100111
001101100
010101111
011101110
100101001
001110111
010110100
011110101
100110010
101110011
001111110
010111101
011111100
100111011
101111010
110111001
000110001001
001010001010
001110001011
010010001100
010110001101
011010001110
011110001111
000110011000
001010011011
001110011010
010010011101
010110011100
011010011111
011110011110
100010010001

What is astonishing, if a bit in nn at position mm is 0, it tells us that 2m2^m additional possible results fulfill the condition kn>nk\oplus n>n, because there are 2m2^m numbers that can become 1, after 010\oplus 1.

That means that we only need to go through the bits of nn and if the bit at the position mm is 0, we add 2m2^m to the counter variable. Since we add only powers of two, we don't need to add the numbers, but can OR them together.

Furthermore, we don't calculate 2m2^m explicitly to save CPU cycles, but use a left-shift. Since we do this for each iteration, we shift by one bit at a time. The whole solution can then be implemented like this:

def theGreatXor(n):
    m = 1
    c = 0
    while n > 0:
        if (n & 1) == 0:
            c|= m
        m<<= 1
        n>>= 1
    return c

This algorithm runs in O(log(n))O(\log(n)). But when thinking about this implementation again, what we are doing actually is inverting nn within the range of the set bits of nn.

So basically, it can be solved with only one n\sim n operation, with \sim denoting binary NOT. The problem with NOT is, that it inverts all leading zeros, so we have to mask the range of the original number nn with 2log2(n)+112^{\lfloor\log_2(n) + 1\rfloor}-1. After that the solution can be shrinked to a one-liner:

def theGreatXor(n):
    return ~n & (2 ** math.floor(math.log2(n) + 1) - 1)