|
| 1 | +# [Problem 3312: Sorted GCD Pair Queries](https://leetcode.com/problems/sorted-gcd-pair-queries/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +I need to produce the sorted list of gcds for all pairs (i < j) and answer queries returning the value at a given index in that sorted list. Directly enumerating all O(n^2) pairs is impossible for n up to 1e5. Observations: |
| 5 | +- nums[i] <= 5e4, so the set of possible gcd values is limited (1..MAXA). |
| 6 | +- If I can count how many pairs have gcd equal to each g, I can produce a frequency histogram of gcd values and answer queries by cumulative counts (binary search). |
| 7 | +- There's a common technique: for each divisor d, count how many numbers in nums are divisible by d => cnt[d]. Number of pairs whose gcd is divisible by d is C(cnt[d], 2). Using inclusion-exclusion over multiples (sieve-like), one can compute number of pairs whose gcd equals exactly d by subtracting contributions of multiples of d. |
| 8 | +- So compute cnt[d] for d=1..MAXA by summing freq[m] over multiples m of d, then pairs_divisible[d] = C(cnt[d],2), then compute exact[d] by iterating d descending and subtracting exact[k*d] for k>=2. |
| 9 | +- After exact counts computed, build prefix sums in ascending gcd order; each query q asks for the smallest gcd value with cumulative count > q. |
| 10 | + |
| 11 | +This seems feasible: MAXA = 5e4, sum_{d=1..MAXA} MAXA/d ~ MAXA * log(MAXA) ~ a few 1e5–1e6 operations — fast. |
| 12 | + |
| 13 | +## Refining the problem, round 2 thoughts |
| 14 | +Edge cases & details: |
| 15 | +- Counts can be large: number of pairs up to ~5e9, so use Python ints (unbounded) or ensure 64-bit. |
| 16 | +- queries are 0-based indices into the sorted array; we need to find smallest g such that cumulative_count[g] > queries[i]. |
| 17 | +- Implementation detail: build arrays of length MAXA+1, with index 0 unused. |
| 18 | +- Complexity: |
| 19 | + - Building cnt via multiples: O(MAXA * H_MAXA) ~ ~5e4 * ~11 = ~5.5e5 operations. |
| 20 | + - Computing exact by iterating multiples again: same magnitude. |
| 21 | + - Answering queries with binary search: O(Q log MAXA). |
| 22 | +- Memory: arrays of size MAXA+1 (~5e4) are fine. |
| 23 | +Alternative approaches: use Mobius transform; but sieve-like subtraction is simple and efficient here. |
| 24 | + |
| 25 | +## Attempted solution(s) |
| 26 | +```python |
| 27 | +from typing import List |
| 28 | +import bisect |
| 29 | + |
| 30 | +class Solution: |
| 31 | + def minPrime(self): # placeholder to satisfy LeetCode environment; not used |
| 32 | + pass |
| 33 | + |
| 34 | + def sortedGcd(self, nums: List[int], queries: List[int]) -> List[int]: |
| 35 | + # Primary solution function (keeps name similar to problem for clarity) |
| 36 | + MAXA = max(nums) |
| 37 | + n = len(nums) |
| 38 | + |
| 39 | + # frequency of each value |
| 40 | + freq = [0] * (MAXA + 1) |
| 41 | + for v in nums: |
| 42 | + freq[v] += 1 |
| 43 | + |
| 44 | + # cnt[d] = number of elements divisible by d |
| 45 | + cnt = [0] * (MAXA + 1) |
| 46 | + for d in range(1, MAXA + 1): |
| 47 | + c = 0 |
| 48 | + for m in range(d, MAXA + 1, d): |
| 49 | + c += freq[m] |
| 50 | + cnt[d] = c |
| 51 | + |
| 52 | + # pairs_divisible[d] = number of pairs (i<j) where both numbers divisible by d |
| 53 | + pairs_div = [0] * (MAXA + 1) |
| 54 | + for d in range(1, MAXA + 1): |
| 55 | + c = cnt[d] |
| 56 | + pairs_div[d] = c * (c - 1) // 2 |
| 57 | + |
| 58 | + # exact[d] = number of pairs with gcd exactly d |
| 59 | + exact = [0] * (MAXA + 1) |
| 60 | + for d in range(MAXA, 0, -1): |
| 61 | + s = 0 |
| 62 | + # subtract contributions from multiples of d (strictly greater than d) |
| 63 | + multiple = 2 * d |
| 64 | + while multiple <= MAXA: |
| 65 | + s += exact[multiple] |
| 66 | + multiple += d |
| 67 | + exact[d] = pairs_div[d] - s |
| 68 | + |
| 69 | + # Build cumulative counts for gcd values in ascending order |
| 70 | + cum = [0] * (MAXA + 1) |
| 71 | + running = 0 |
| 72 | + for d in range(1, MAXA + 1): |
| 73 | + running += exact[d] |
| 74 | + cum[d] = running |
| 75 | + |
| 76 | + # For each query (0-based index), find smallest d with cum[d] > q |
| 77 | + ans = [] |
| 78 | + for q in queries: |
| 79 | + # need first index with cumulative count >= q+1 |
| 80 | + pos = bisect.bisect_left(cum, q + 1, 1, MAXA + 1) |
| 81 | + ans.append(pos) |
| 82 | + return ans |
| 83 | + |
| 84 | +# LeetCode signature compatibility |
| 85 | +class Solution: |
| 86 | + def countSortedGcdPairQueries(self, nums: List[int], queries: List[int]) -> List[int]: |
| 87 | + # The function called by judge will likely be sortedGcdPairQueries or similar. |
| 88 | + # Provide a wrapper to the implemented logic above. |
| 89 | + # For LeetCode submission use the standard name: |
| 90 | + MAXA = max(nums) |
| 91 | + freq = [0] * (MAXA + 1) |
| 92 | + for v in nums: |
| 93 | + freq[v] += 1 |
| 94 | + |
| 95 | + cnt = [0] * (MAXA + 1) |
| 96 | + for d in range(1, MAXA + 1): |
| 97 | + for m in range(d, MAXA + 1, d): |
| 98 | + cnt[d] += freq[m] |
| 99 | + |
| 100 | + pairs_div = [0] * (MAXA + 1) |
| 101 | + for d in range(1, MAXA + 1): |
| 102 | + c = cnt[d] |
| 103 | + pairs_div[d] = c * (c - 1) // 2 |
| 104 | + |
| 105 | + exact = [0] * (MAXA + 1) |
| 106 | + for d in range(MAXA, 0, -1): |
| 107 | + s = 0 |
| 108 | + for m in range(2 * d, MAXA + 1, d): |
| 109 | + s += exact[m] |
| 110 | + exact[d] = pairs_div[d] - s |
| 111 | + |
| 112 | + cum = [0] * (MAXA + 1) |
| 113 | + run = 0 |
| 114 | + for d in range(1, MAXA + 1): |
| 115 | + run += exact[d] |
| 116 | + cum[d] = run |
| 117 | + |
| 118 | + import bisect |
| 119 | + res = [] |
| 120 | + for q in queries: |
| 121 | + pos = bisect.bisect_left(cum, q + 1, 1, MAXA + 1) |
| 122 | + res.append(pos) |
| 123 | + return res |
| 124 | + |
| 125 | +# For direct LeetCode submission, the required class/method name is: |
| 126 | +# class Solution: |
| 127 | +# def gcdQueries(self, nums: List[int], queries: List[int]) -> List[int]: |
| 128 | +# Replace the wrapper name above accordingly. |
| 129 | +``` |
| 130 | + |
| 131 | +- Notes about the approach: |
| 132 | + - We count for each d how many array elements are divisible by d (cnt[d]). |
| 133 | + - pairs_div[d] = C(cnt[d], 2) counts pairs with gcd multiple of d. |
| 134 | + - exact[d] is computed by inclusion-exclusion: exact[d] = pairs_div[d] - sum_{k>=2} exact[k*d]. We process d from large to small so multiples' exact counts are already known. |
| 135 | + - Build cumulative counts cum[d] = #pairs with gcd <= d. For a 0-based query q, answer is smallest d with cum[d] > q (binary search). |
| 136 | +- Complexity: |
| 137 | + - Time: O(MAXA * (1 + 1/2 + 1/3 + ...)) ~ O(MAXA log MAXA) for the sieving steps plus O(Q log MAXA) for answering queries. With MAXA <= 5e4 this is fast. |
| 138 | + - Space: O(MAXA) for arrays freq, cnt, pairs_div, exact, cum. |
| 139 | + |
| 140 | +This solution is efficient and handles large n since it avoids enumerating all pairs directly. |
0 commit comments