Maximum Xor Product
MedPrompt
Given three integers a, b, and n, return the maximum value of (a XOR x) * (b XOR x) where 0 <= x < 2n.
Since the answer may be too large, return it modulo 109 + 7.
Note that XOR is the bitwise XOR operation.
Example 1:
Input: a = 12, b = 5, n = 4
Output: 98
Explanation: For x = 2, (a XOR x) = 14 and (b XOR x) = 7. Hence, (a XOR x) * (b XOR x) = 98.
It can be shown that 98 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.Example 2:
Input: a = 6, b = 7 , n = 5
Output: 930
Explanation: For x = 25, (a XOR x) = 31 and (b XOR x) = 30. Hence, (a XOR x) * (b XOR x) = 930.
It can be shown that 930 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.Example 3:
Input: a = 1, b = 6, n = 3
Output: 12
Explanation: For x = 5, (a XOR x) = 4 and (b XOR x) = 3. Hence, (a XOR x) * (b XOR x) = 12.
It can be shown that 12 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.
Constraints:
0 <= a, b < 2500 <= n <= 50
Approaches
2 approaches with complexity analysis and trade-offs.
The brute-force approach is the most straightforward way to solve the problem. It involves checking every single possible value for x within its allowed range, 0 <= x < 2^n. For each x, we compute the expression (a XOR x) * (b XOR x) and keep track of the maximum value found. While simple to conceptualize, this method is computationally expensive and not feasible for the problem's constraints.
Algorithm
- Initialize a variable
max_producttoBigInteger.ZERO. - Determine the upper bound for
x, which is2^n. Let's call itlimit. - Loop
xfrom0tolimit - 1.- For each
x, calculateval_a = a XOR xandval_b = b XOR x. - Compute the product
current_product = val_a * val_b. - Compare
current_productwithmax_productand updatemax_productif the current product is larger.
- For each
- After the loop finishes,
max_productwill hold the maximum possible product. - Return
max_productmodulo10^9 + 7.
Walkthrough
This method iterates through all possible values of x from 0 to 2^n - 1. In each iteration, it calculates the two XORed values, a XOR x and b XOR x, and their product. It maintains a variable, max_product, initialized to zero, and updates it whenever a larger product is found.
Since a, b, and x can be large, their XOR results can also be large. The product (a XOR x) * (b XOR x) can exceed the capacity of a standard 64-bit integer (long in Java). For instance, if a, b, and x are around 2^50, the product can be around 2^100. Therefore, it's necessary to use a class that can handle arbitrarily large integers, such as java.math.BigInteger.
import java.math.BigInteger; class Solution { public int maximumXorProduct(long a, long b, int n) { BigInteger maxProduct = BigInteger.ZERO; long limit = 1L << n; BigInteger bigA = BigInteger.valueOf(a); BigInteger bigB = BigInteger.valueOf(b); BigInteger mod = new BigInteger("1000000007"); for (long x = 0; x < limit; x++) { BigInteger bigX = BigInteger.valueOf(x); BigInteger valA = bigA.xor(bigX); BigInteger valB = bigB.xor(bigX); BigInteger currentProduct = valA.multiply(valB); if (currentProduct.compareTo(maxProduct) > 0) { maxProduct = currentProduct; } } return maxProduct.mod(mod).intValue(); }}Complexity
Time
O(2^n). The loop runs `2^n` times. With `n` up to 50, `2^50` is approximately `10^15`, which is computationally infeasible.
Space
O(1) (excluding the storage for `BigInteger` which depends on the magnitude of the numbers, but is constant for the given constraints).
Trade-offs
Pros
Simple to understand and implement.
Guaranteed to find the correct maximum value if implemented correctly.
Cons
Extremely inefficient, with a time complexity that is exponential in
n.Will result in a 'Time Limit Exceeded' error for the given constraints (
nup to 50).Requires using
BigIntegerto handle potentially very large products, which adds complexity and overhead.
A highly efficient solution can be achieved using a greedy approach that constructs the optimal values of A = a XOR x and B = b XOR x bit by bit, from most significant to least significant. The core idea is that to maximize a product A * B, we should try to make both A and B as large as possible. When a conflict arises (i.e., we can only make one of them larger at a certain bit position), we make a choice that keeps their values as close as possible, which is a good heuristic for maximizing their product.
Algorithm
- Initialize two
longvariables,resAandresB, to 0. These will be built into the finala XOR xandb XOR xvalues. - Iterate from the most significant bit, say 49, down to 0. Let the current bit be
i. - For each bit
i, get thei-th bits ofaandb, let's call thembit_aandbit_b. - If
i >= n: Thei-th bit ofxmust be 0. Thei-th bits of the results are determined solely byaandb. Set thei-th bit ofresAtobit_aandresBtobit_b. - If
i < n: We can choose thei-th bit ofx.- If
bit_ais the same asbit_b: We can choosex_ito make the resulting bits(a XOR x)_iand(b XOR x)_iboth 1. This is always optimal as it makes both numbers larger. So, we set thei-th bit in bothresAandresBto 1. - If
bit_ais different frombit_b: The resulting bits must be different (one 1, one 0). To maximize the product, we want to keepresAandresBas close in value as possible. We compare the prefixes ofresAandresBbuilt so far (from bits higher thani).- If
resAis currently smaller thanresB, we give the 1-bit toresAto help it catch up. - Otherwise (if
resAis greater or equal), we give the 1-bit toresB.
- If
- If
- After the loop,
resAandresBhold the optimal values. - Calculate
(resA % MOD) * (resB % MOD) % MODand return the result.
Walkthrough
We iterate through the bits from a high number (like 49, since a, b < 2^50) down to 0. We build up our target numbers, let's call them resA and resB, which will eventually be a XOR x and b XOR x.
For bits i at or above n, the corresponding bit of x must be 0. Thus, the bits of resA and resB are fixed and equal to the corresponding bits of a and b.
For bits i below n, we have a choice for x_i (0 or 1).
- If the
i-th bits ofaandbare the same, we can choosex_ito make thei-th bit of bothresAandresBequal to 1. This is always the best choice as it maximizes both numbers. - If the
i-th bits ofaandbare different, we can only set thei-th bit to 1 for one of the results, while the other gets a 0. To maximize the final product, we should try to makeresAandresBas close to each other as possible. We look at the values ofresAandresBconstructed so far from the higher bits. IfresAis currently smaller thanresB, we assign the 1-bit toresAfor the current positioni. Otherwise, we assign it toresB.
This greedy strategy ensures that at each step, we make a locally optimal choice that leads to the global maximum.
class Solution { public int maximumXorProduct(long a, long b, int n) { long resA = 0; long resB = 0; long MOD = 1_000_000_007; for (int i = 49; i >= 0; i--) { long mask = 1L << i; long bit_a = a & mask; long bit_b = b & mask; if (i < n) { // We can choose x_i if (bit_a == bit_b) { // If bits of a and b are same, we can make both resulting bits 1. // This is always optimal. e.g., if a_i=b_i=0, choose x_i=1 -> resA_i=1, resB_i=1. // if a_i=b_i=1, choose x_i=0 -> resA_i=1, resB_i=1. resA |= mask; resB |= mask; } else { // Bits are different, one result must be 1, other 0. // To maximize product, give the '1' to the smaller number to balance them. if (resA < resB) { resA |= mask; // Make resA larger } else { resB |= mask; // Make resB larger (or if they are equal) } } } else { // x_i must be 0, so result bits are same as a_i and b_i if (bit_a != 0) { resA |= mask; } if (bit_b != 0) { resB |= mask; } } } resA %= MOD; resB %= MOD; return (int) ((resA * resB) % MOD); }}Complexity
Time
O(k), where `k` is the number of bits in the numbers (e.g., 50). This is effectively constant time, O(1).
Space
O(1), as it only uses a few variables to store intermediate results.
Trade-offs
Pros
Extremely fast, with a constant time complexity.
Efficiently solves the problem for the given large constraints.
Requires only basic integer types (
long) and bitwise operations.
Cons
The greedy logic is non-trivial and requires careful reasoning about bitwise operations and their effect on the product.
Solutions
Solution
class Solution {public int maximumXorProduct(long a, long b, int n) { final int mod = (int)1 e9 + 7; long ax = (a >> n) << n; long bx = (b >> n) << n; for (int i = n - 1; i >= 0; --i) { long x = a >> i & 1; long y = b >> i & 1; if (x == y) { ax |= 1L << i; bx |= 1L << i; } else if (ax < bx) { ax |= 1L << i; } else { bx |= 1L << i; } } ax %= mod; bx %= mod; return (int)(ax * bx % mod); }}class Solution {public: int maximumXorProduct(long long a, long long b, int n) { const int mod = 1e9 + 7; long long ax = (a >> n) << n, bx = (b >> n) << n; for (int i = n - 1; ~i; --i) { int x = a >> i & 1, y = b >> i & 1; if (x == y) { ax |= 1LL << i; bx |= 1LL << i; } else if (ax < bx) { ax |= 1LL << i; } else { bx |= 1LL << i; } } ax %= mod; bx %= mod; return ax * bx % mod; }};class Solution: def maximumXorProduct(self, a: int, b: int, n: int) -> int: mod = 10 ** 9 + 7 ax, bx = (a >> n) << n, (b >> n) << n for i in range(n - 1, - 1, - 1): x = a >> i & 1 y = b >> i & 1 if x == y: ax |= 1 << i bx |= 1 << i elif ax > bx: bx |= 1 << i else: ax |= 1 << i return ax * bx % modVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.