You are given a 0-indexed 2D array variables where variables[i] = [ai, bi, ci, mi], and an integer target.
An index i is good if the following formula holds:
0 <= i < variables.length((aibi % 10)ci) % mi == targetReturn an array consisting of good indices in any order.
Example 1:
Input: variables = [[2,3,3,10],[3,3,3,1],[6,1,1,4]], target = 2 Output: [0,2] Explanation: For each index i in the variables array: 1) For the index 0, variables[0] = [2,3,3,10], (23 % 10)3 % 10 = 2. 2) For the index 1, variables[1] = [3,3,3,1], (33 % 10)3 % 1 = 0. 3) For the index 2, variables[2] = [6,1,1,4], (61 % 10)1 % 4 = 2. Therefore we return [0,2] as the answer.
Example 2:
Input: variables = [[39,3,1000,1000]], target = 17 Output: [] Explanation: For each index i in the variables array: 1) For the index 0, variables[0] = [39,3,1000,1000], (393 % 10)1000 % 1000 = 1. Therefore we return [] as the answer.
Constraints:
1 <= variables.length <= 100variables[i] == [ai, bi, ci, mi]1 <= ai, bi, ci, mi <= 1030 <= target <= 103When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
For double modular exponentiation, we need to calculate one modular exponentiation and then use that result as the exponent in another modular exponentiation. The brute force method directly calculates each exponentiation separately without trying to optimize anything.
Here's how the algorithm would work step-by-step:
def double_modular_exponentiation(base, exponent1, modulus1, modulus2):
# Calculate the first modular exponentiation
inner_exponentiation_result = 1
base_for_exponentiation = base % modulus1
exponent_loop_counter = 0
while exponent_loop_counter < exponent1:
inner_exponentiation_result = (inner_exponentiation_result * base_for_exponentiation) % modulus1
exponent_loop_counter += 1
# Use the result of the first exponentiation as the exponent for the second
outer_exponentiation_result = 1
base_for_exponentiation = base % modulus2
# Reset loop counter
exponent_loop_counter = 0
while exponent_loop_counter < inner_exponentiation_result:
# To avoid integer overflow, take modulus
outer_exponentiation_result = (outer_exponentiation_result * base_for_exponentiation) % modulus2
exponent_loop_counter += 1
# Final result after performing both modular exponentiations
return outer_exponentiation_resultThe core idea is to break down the extremely large exponents into smaller, manageable parts. We will leverage properties of modular arithmetic to efficiently compute the results without dealing with huge numbers directly.
Here's how the algorithm would work step-by-step:
def double_modular_exponentiation(base, exponent_one, modulus_one, exponent_two, modulus_two):
result_one = modular_exponentiation(base, exponent_one, modulus_one)
final_result = modular_exponentiation(result_one, exponent_two, modulus_two)
return final_result
def modular_exponentiation(base_value, exponent, modulus):
result = 1
base_value %= modulus
# Iterate while the exponent is greater than 0
while exponent > 0:
#If the least significant bit is one.
if exponent % 2 == 1:
result = (result * base_value) % modulus
# Equivalent to base = base * base.
base_value = (base_value * base_value) % modulus
# Equivalent to exponent = exponent / 2.
exponent //= 2
return result| Case | How to Handle |
|---|---|
| Base is 0 | If base is 0, and exponent is positive, the result should be 0; if the exponent is 0, the result should be 1, handle appropriately depending on exponent's value. |
| Base is 1 | If base is 1, the result will always be 1 regardless of the exponent, return 1 to avoid unnecessary calculations. |
| Exponent is 0 | Any number (except 0) raised to the power of 0 is 1; return 1 after checking base is non-zero. |
| Exponent is 1 | Any number raised to the power of 1 is itself; return the base immediately. |
| Modulus is 1 | If modulus is 1, the result will always be 0; return 0 to avoid any further calculation. |
| Base, exponent, or modulus is negative | Handle negative base by taking the modulus after the calculation; exponent needs checking for algorithm correctness; modulus must be positive, throw error if not. |
| Integer overflow during exponentiation | Use modular arithmetic during intermediate calculations to prevent overflow, ensuring all calculations remain within the bounds of the data type to avoid inaccuracies. |
| Very large exponent | Employ the method of exponentiation by squaring (binary exponentiation) to efficiently compute large powers, significantly reducing the number of operations. |