DDSA Solutions

3336. Find the Number of Subsequences With Equal GCD

Time: O(n * M^2)
Space: O(M^2)

Problem Overview

Count ordered pairs of disjoint non-empty subsequences with the same GCD.

Intuition

Count ordered pairs of disjoint non-empty subsequences with the same GCD. Constraints are tiny (n, values ≤ 200), so track every possible GCD pair while scanning the array. dp[x][y] = number of ways to assign processed elements so the first subsequence has GCD x and the second has GCD y (0 means that subsequence is still empty).

Algorithm

  1. 1Let M = max(nums). Initialize dp[0][0] = 1 (both subsequences empty).
  2. 2For each num, build a fresh table newDp. For every existing state (x, y) with count c:
  3. 3 • Skip num → add c to newDp[x][y].
  4. 4 • Append to first → add c to newDp[gcd(x, num)][y] (gcd(0, num) = num).
  5. 5 • Append to second → add c to newDp[x][gcd(y, num)].
  6. 6All additions are modulo 10^9+7; replace dp with newDp.
  7. 7Answer = sum of dp[g][g] for g = 1 … M (both non-empty and equal GCD).

Example Walkthrough

Input: nums = [10, 20, 30]

  1. 1.Start dp[0][0] = 1.
  2. 2.After 10: can leave both empty, put 10 in first (GCD 10), or put 10 in second.
  3. 3.After 20 and 30: the only equal non-empty pairs are ([10], [20,30]) and ([20,30], [10]) — both have GCD 10.
  4. 4.Summing dp[g][g] for g ≥ 1 yields 2.

Output: 2

Common Pitfalls

  • Subsequences must be index-disjoint — each element goes to at most one of the two sequences (or neither).
  • Do not count dp[0][0]; both subsequences must be non-empty (sum from g = 1).
  • Use a separate newDp table each step — updating in place double-counts transitions.
  • gcd(0, x) = x is required so the first element placed into an empty subsequence sets its GCD.
3336.cs
C#
// Approach: DP over disjoint subsequence pairs. dp[x][y] = ways to form two subsequences
// with GCDs x and y (0 = empty). For each num: skip it, append to first, or append to second.
// Answer is sum of dp[g][g] for g >= 1 (both non-empty with equal GCD), mod 1e9+7.
// Time: O(n * M^2) Space: O(M^2) where M = max(nums)
public class Solution
{
    private const int MOD = 1_000_000_007;

    public int SubsequencePairCount(int[] nums)
    {
        int n = nums.Length;
        int maxNum = 0;
        foreach (var num in nums)
        {
            if (num > maxNum)
                maxNum = num;
        }

        int[,] dp = new int[maxNum + 1, maxNum + 1];
        dp[0, 0] = 1;

        foreach (var num in nums)
        {
            int[,] newDp = new int[maxNum + 1, maxNum + 1];
            for (int x = 0; x <= maxNum; ++x)
            {
                for (int y = 0; y <= maxNum; ++y)
                {
                    // 1. Skip `num`.
                    newDp[x, y] = (newDp[x, y] + dp[x, y]) % MOD;
                    // 2. Pick `num` in the first subsequence.
                    int newX = Gcd(x, num);
                    newDp[newX, y] = (newDp[newX, y] + dp[x, y]) % MOD;
                    // 3. Pick `num` in the second subsequence.
                    int newY = Gcd(y, num);
                    newDp[x, newY] = (newDp[x, newY] + dp[x, y]) % MOD;
                }
            }
            dp = newDp;
        }

        int ans = 0;
        for (int g = 1; g <= maxNum; ++g)
            ans = (ans + dp[g, g]) % MOD;

        return ans;
    }

    private int Gcd(int a, int b)
    {
        return b == 0 ? a : Gcd(b, a % b);
    }
}
Was this solution helpful?

Related Problems