Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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 <= 103Problem summary: 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 == target Return an array consisting of good indices in any order.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Math
[[2,3,3,10],[3,3,3,1],[6,1,1,4]] 2
[[39,3,1000,1000]] 17
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2961: Double Modular Exponentiation
class Solution {
public List<Integer> getGoodIndices(int[][] variables, int target) {
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < variables.length; ++i) {
var e = variables[i];
int a = e[0], b = e[1], c = e[2], m = e[3];
if (qpow(qpow(a, b, 10), c, m) == target) {
ans.add(i);
}
}
return ans;
}
private int qpow(long a, int n, int mod) {
long ans = 1;
for (; n > 0; n >>= 1) {
if ((n & 1) == 1) {
ans = ans * a % mod;
}
a = a * a % mod;
}
return (int) ans;
}
}
// Accepted solution for LeetCode #2961: Double Modular Exponentiation
func getGoodIndices(variables [][]int, target int) (ans []int) {
qpow := func(a, n, mod int) int {
ans := 1
for ; n > 0; n >>= 1 {
if n&1 == 1 {
ans = ans * a % mod
}
a = a * a % mod
}
return ans
}
for i, e := range variables {
a, b, c, m := e[0], e[1], e[2], e[3]
if qpow(qpow(a, b, 10), c, m) == target {
ans = append(ans, i)
}
}
return
}
# Accepted solution for LeetCode #2961: Double Modular Exponentiation
class Solution:
def getGoodIndices(self, variables: List[List[int]], target: int) -> List[int]:
return [
i
for i, (a, b, c, m) in enumerate(variables)
if pow(pow(a, b, 10), c, m) == target
]
// Accepted solution for LeetCode #2961: Double Modular Exponentiation
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #2961: Double Modular Exponentiation
// class Solution {
// public List<Integer> getGoodIndices(int[][] variables, int target) {
// List<Integer> ans = new ArrayList<>();
// for (int i = 0; i < variables.length; ++i) {
// var e = variables[i];
// int a = e[0], b = e[1], c = e[2], m = e[3];
// if (qpow(qpow(a, b, 10), c, m) == target) {
// ans.add(i);
// }
// }
// return ans;
// }
//
// private int qpow(long a, int n, int mod) {
// long ans = 1;
// for (; n > 0; n >>= 1) {
// if ((n & 1) == 1) {
// ans = ans * a % mod;
// }
// a = a * a % mod;
// }
// return (int) ans;
// }
// }
// Accepted solution for LeetCode #2961: Double Modular Exponentiation
function getGoodIndices(variables: number[][], target: number): number[] {
const qpow = (a: number, n: number, mod: number) => {
let ans = 1;
for (; n; n >>= 1) {
if (n & 1) {
ans = Number((BigInt(ans) * BigInt(a)) % BigInt(mod));
}
a = Number((BigInt(a) * BigInt(a)) % BigInt(mod));
}
return ans;
};
const ans: number[] = [];
for (let i = 0; i < variables.length; ++i) {
const [a, b, c, m] = variables[i];
if (qpow(qpow(a, b, 10), c, m) === target) {
ans.push(i);
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.