Given a long integer , count the number of values of satisfying the following conditions:
where and are long integers and is the bitwise XOR operator.
You are given queries, and each query is in the form of a long integer denoting . 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 . Condition requires The following tests are run:
We find that there are values meeting the first condition: and .
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 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 in binary notation:
01 | 10 | 11 |
01 | 11 | 10 |
10 | 11 | 01 |
001 | 100 | 101 |
010 | 100 | 110 |
011 | 100 | 111 |
001 | 101 | 100 |
010 | 101 | 111 |
011 | 101 | 110 |
100 | 101 | 001 |
001 | 110 | 111 |
010 | 110 | 100 |
011 | 110 | 101 |
100 | 110 | 010 |
101 | 110 | 011 |
001 | 111 | 110 |
010 | 111 | 101 |
011 | 111 | 100 |
100 | 111 | 011 |
101 | 111 | 010 |
110 | 111 | 001 |
0001 | 1000 | 1001 |
0010 | 1000 | 1010 |
0011 | 1000 | 1011 |
0100 | 1000 | 1100 |
0101 | 1000 | 1101 |
0110 | 1000 | 1110 |
0111 | 1000 | 1111 |
0001 | 1001 | 1000 |
0010 | 1001 | 1011 |
0011 | 1001 | 1010 |
0100 | 1001 | 1101 |
0101 | 1001 | 1100 |
0110 | 1001 | 1111 |
0111 | 1001 | 1110 |
1000 | 1001 | 0001 |
What is astonishing, if a bit in at position is 0, it tells us that additional possible results fulfill the condition , because there are numbers that can become 1, after .
That means that we only need to go through the bits of and if the bit at the position is 0, we add 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 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 . But when thinking about this implementation again, what we are doing actually is inverting within the range of the set bits of .
So basically, it can be solved with only one operation, with 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 with . After that the solution can be shrinked to a one-liner:
def theGreatXor(n):
return ~n & (2 ** math.floor(math.log2(n) + 1) - 1)