diff --git a/problems/3336-find-the-number-of-subsequences-with-equal-gcd/analysis_daily_20260714.md b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/analysis_daily_20260714.md new file mode 100644 index 0000000..e1a7b0d --- /dev/null +++ b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/analysis_daily_20260714.md @@ -0,0 +1,119 @@ +# 3336. Find the Number of Subsequences With Equal GCD + +[LeetCode Link](https://leetcode.com/problems/find-the-number-of-subsequences-with-equal-gcd/) + +Difficulty: Hard +Topics: Array, Math, Dynamic Programming, Number Theory +Acceptance Rate: 44.8% + +This one is genuinely tricky — it combines counting over exponentially many +subsequence pairs with GCD tracking. Don't be discouraged if the brute-force +"try every split" idea feels hopeless; that feeling is exactly the signal that +pushes you toward the DP formulation below. Take it hint by hint. + +## Hints + +### Hint 1 + +There are up to `2^n` subsequences, and you are pairing them, so enumerating +pairs directly is impossible for `n` up to 200. Whenever you must *count* +configurations over an exponential space, think dynamic programming where the +**state captures just enough summary information** to make the count. Ask +yourself: what is the minimal summary of a chosen subsequence that this problem +actually cares about? + +### Hint 2 + +The only property of a subsequence that matters is its GCD. And there is a +second helpful fact: the values are bounded by `1 <= nums[i] <= 200`, so any +GCD is an integer in `[1, 200]`. That small range is your invitation to make the +GCD part of the DP state. Consider a state that tracks the current GCD of +`seq1` and the current GCD of `seq2` simultaneously as you scan the array. + +### Hint 3 + +Process elements one at a time and let `dp[a][b]` be the number of ways to +assign the elements seen so far to three buckets — put it in `seq1`, put it in +`seq2`, or leave it out — so that `seq1` currently has GCD `a` and `seq2` has +GCD `b`. Use `0` as a sentinel meaning "still empty", which is perfect because +`gcd(0, x) = x`. Each new element branches into exactly three transitions. At +the end, sum `dp[g][g]` over all `g >= 1` (both non-empty, GCDs equal). The +disjointness constraint is handled for free: each index lands in at most one of +the two subsequences because a single element can only take one of the three +choices. + +## Approach + +We build the answer incrementally with a 2-D DP over GCD values. + +**State.** Let `dp[a][b]` = the number of ways to have processed some prefix of +`nums`, assigning each processed element to `seq1`, `seq2`, or "unused", such +that the running GCD of `seq1` is `a` and the running GCD of `seq2` is `b`. +Both `a` and `b` range over `0..maxV` where `maxV = max(nums)`, and the value +`0` is a sentinel meaning "this subsequence is still empty". + +**Why `0` works so well.** The standard Euclidean GCD satisfies `gcd(0, x) = x`. +So if a subsequence is empty (GCD `0`) and we add the first element `x`, the new +GCD becomes `gcd(0, x) = x` automatically — no special casing needed for the +first element. + +**Initialization.** `dp[0][0] = 1`: before processing anything, both +subsequences are empty, and there is exactly one such (empty) assignment. + +**Transition.** For each element `num`, we compute a fresh table `ndp` from `dp`. +Every existing state `dp[a][b]` fans out into three choices: + +- *Skip* `num`: it contributes to `ndp[a][b]` unchanged. (Implemented by + copying `dp` into `ndp` up front.) +- *Put `num` in `seq1`*: the GCD of `seq1` becomes `gcd(a, num)`, contributing + to `ndp[gcd(a, num)][b]`. +- *Put `num` in `seq2`*: the GCD of `seq2` becomes `gcd(b, num)`, contributing + to `ndp[a][gcd(b, num)]`. + +All additions are taken modulo `1e9 + 7`. + +**Answer.** After all elements are processed, every valid pair `(seq1, seq2)` +with both non-empty and equal GCD `g` is counted in `dp[g][g]` for some +`g >= 1`. We sum `dp[g][g]` over `g` from `1` to `maxV`. States with `a = 0` or +`b = 0` are excluded because one of the subsequences would be empty, which the +problem forbids. + +**Why disjointness is automatic.** Each element chooses exactly one of the three +buckets, so no index can appear in both `seq1` and `seq2`. The "unused" bucket +is what lets us range over *all* subsequence pairs rather than partitions of the +whole array. + +**Worked micro-example.** For `nums = [7, 7]`, after processing both elements +`dp[7][7]` counts: put element 0 in `seq1` and element 1 in `seq2`, or the +reverse — that is `2` ordered pairs, matching the fact that `(seq1, seq2)` is an +ordered pair (the problem counts both directions, as its own examples show). + +## Complexity Analysis + +Let `n = len(nums)` and `M = max(nums)` (at most 200). + +Time Complexity: O(n · M²) — for each of the `n` elements we sweep the full +`(M+1) × (M+1)` table, doing O(1) work (two GCD computations plus modular adds) +per cell. The GCD itself is O(log M), so a tight bound is O(n · M² · log M), +which for the given constraints is comfortably fast. + +Space Complexity: O(M²) — two `(M+1) × (M+1)` tables (`dp` and `ndp`); we keep +only the current and next layers, not one per element. + +## Edge Cases + +- **Single element** (`n = 1`): impossible to form two disjoint non-empty + subsequences, so the answer is `0`. The DP handles this because no state with + both `a >= 1` and `b >= 1` can ever be reached. +- **All elements equal** (e.g. `[1,1,1,1]`): many valid pairs; a good stress + test that the counting (and the modulo) is right. The expected answer is `50`. +- **Coprime pair** (e.g. `[2, 3]`): each single-element GCD differs, and there + are not enough elements to build a common GCD, so the answer is `0`. +- **Ordered pairs**: `(seq1, seq2)` and `(seq2, seq1)` are counted separately — + the DP naturally produces both because the two "put in seq1" / "put in seq2" + transitions are symmetric but distinct. +- **Modulo overflow**: the count can be astronomically large, so every addition + must be reduced modulo `1e9 + 7`. Forgetting this on any transition silently + corrupts the result once counts exceed the modulus. +- **Empty-subsequence sentinel**: excluding `g = 0` from the final sum is + essential — states where either subsequence is empty must not be counted. diff --git a/problems/3336-find-the-number-of-subsequences-with-equal-gcd/problem.md b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/problem.md new file mode 100644 index 0000000..371f074 --- /dev/null +++ b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/problem.md @@ -0,0 +1,86 @@ +--- +number: "3336" +frontend_id: "3336" +title: "Find the Number of Subsequences With Equal GCD" +slug: "find-the-number-of-subsequences-with-equal-gcd" +difficulty: "Hard" +topics: + - "Array" + - "Math" + - "Dynamic Programming" + - "Number Theory" +acceptance_rate: 4476.3 +is_premium: false +created_at: "2026-07-14T03:43:14.447424+00:00" +fetched_at: "2026-07-14T03:43:14.447424+00:00" +link: "https://leetcode.com/problems/find-the-number-of-subsequences-with-equal-gcd/" +date: "2026-07-14" +--- + +# 3336. Find the Number of Subsequences With Equal GCD + +You are given an integer array `nums`. + +Your task is to find the number of pairs of **non-empty** subsequences `(seq1, seq2)` of `nums` that satisfy the following conditions: + + * The subsequences `seq1` and `seq2` are **disjoint** , meaning **no index** of `nums` is common between them. + * The GCD of the elements of `seq1` is equal to the GCD of the elements of `seq2`. + + + +Return the total number of such pairs. + +Since the answer may be very large, return it **modulo** `109 + 7`. + + + +**Example 1:** + +**Input:** nums = [1,2,3,4] + +**Output:** 10 + +**Explanation:** + +The subsequence pairs which have the GCD of their elements equal to 1 are: + + * `([**_1_** , 2, 3, 4], [1, **_2_** , **_3_** , 4])` + * `([**_1_** , 2, 3, 4], [1, **_2_** , **_3_** , **_4_**])` + * `([**_1_** , 2, 3, 4], [1, 2, **_3_** , **_4_**])` + * `([**_1_** , **_2_** , 3, 4], [1, 2, **_3_** , **_4_**])` + * `([**_1_** , 2, 3, **_4_**], [1, **_2_** , **_3_** , 4])` + * `([1, **_2_** , **_3_** , 4], [**_1_** , 2, 3, 4])` + * `([1, **_2_** , **_3_** , 4], [**_1_** , 2, 3, **_4_**])` + * `([1, **_2_** , **_3_** , **_4_**], [**_1_** , 2, 3, 4])` + * `([1, 2, **_3_** , **_4_**], [**_1_** , 2, 3, 4])` + * `([1, 2, **_3_** , **_4_**], [**_1_** , **_2_** , 3, 4])` + + + +**Example 2:** + +**Input:** nums = [10,20,30] + +**Output:** 2 + +**Explanation:** + +The subsequence pairs which have the GCD of their elements equal to 10 are: + + * `([**_10_** , 20, 30], [10, **_20_** , **_30_**])` + * `([10, **_20_** , **_30_**], [**_10_** , 20, 30])` + + + +**Example 3:** + +**Input:** nums = [1,1,1,1] + +**Output:** 50 + + + +**Constraints:** + + * `1 <= nums.length <= 200` + * `1 <= nums[i] <= 200` diff --git a/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714.go b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714.go new file mode 100644 index 0000000..6c07b9c --- /dev/null +++ b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714.go @@ -0,0 +1,73 @@ +package main + +// Approach: dynamic programming over (gcd of seq1, gcd of seq2). +// +// Process the elements one at a time. A DP state dp[a][b] holds the number of +// ways to assign the elements seen so far to one of three buckets — seq1, seq2, +// or "unused" — such that the running GCD of seq1 is `a` and the running GCD of +// seq2 is `b`. We use the sentinel value 0 to mean "the subsequence is still +// empty", which works nicely because gcd(0, x) == x, so adding the first +// element to an empty subsequence simply sets its GCD to that element. +// +// For each new element `num`, every existing state can transition three ways: +// - skip num -> dp[a][b] stays as dp[a][b] +// - put num in seq1 -> contributes to dp[gcd(a, num)][b] +// - put num in seq2 -> contributes to dp[a][gcd(b, num)] +// +// The final answer is the sum over all g >= 1 of dp[g][g]: both subsequences +// are non-empty (GCD != 0) and their GCDs are equal. +const mod = 1_000_000_007 + +func subsequencePairCount(nums []int) int { + maxV := 0 + for _, v := range nums { + if v > maxV { + maxV = v + } + } + + // dp[a][b]: a, b range over 0..maxV, with 0 meaning "empty subsequence". + dp := make([][]int, maxV+1) + for i := range dp { + dp[i] = make([]int, maxV+1) + } + dp[0][0] = 1 // both subsequences start empty + + for _, num := range nums { + ndp := make([][]int, maxV+1) + for i := range ndp { + ndp[i] = make([]int, maxV+1) + copy(ndp[i], dp[i]) // "skip num" transition + } + for a := 0; a <= maxV; a++ { + for b := 0; b <= maxV; b++ { + ways := dp[a][b] + if ways == 0 { + continue + } + // put num in seq1 + na := gcd(a, num) + ndp[na][b] = (ndp[na][b] + ways) % mod + // put num in seq2 + nb := gcd(b, num) + ndp[a][nb] = (ndp[a][nb] + ways) % mod + } + } + dp = ndp + } + + ans := 0 + for g := 1; g <= maxV; g++ { + ans = (ans + dp[g][g]) % mod + } + return ans +} + +// gcd returns the greatest common divisor of a and b. +// gcd(0, x) == x, which lets 0 act as the "empty subsequence" sentinel. +func gcd(a, b int) int { + for b != 0 { + a, b = b, a%b + } + return a +} diff --git a/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714_test.go b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714_test.go new file mode 100644 index 0000000..7d51d96 --- /dev/null +++ b/problems/3336-find-the-number-of-subsequences-with-equal-gcd/solution_daily_20260714_test.go @@ -0,0 +1,28 @@ +package main + +import "testing" + +func TestSolution(t *testing.T) { + tests := []struct { + name string + nums []int + expected int + }{ + {"example 1: nums = [1,2,3,4]", []int{1, 2, 3, 4}, 10}, + {"example 2: nums = [10,20,30]", []int{10, 20, 30}, 2}, + {"example 3: nums = [1,1,1,1]", []int{1, 1, 1, 1}, 50}, + {"edge case: single element cannot form two subsequences", []int{5}, 0}, + {"edge case: two equal elements (ordered pairs)", []int{7, 7}, 2}, + {"edge case: two coprime elements have no equal-gcd pair", []int{2, 3}, 0}, + {"edge case: max value repeated", []int{200, 200, 200}, 12}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := subsequencePairCount(tt.nums) + if result != tt.expected { + t.Errorf("subsequencePairCount(%v) = %d, want %d", tt.nums, result, tt.expected) + } + }) + } +}