Binary Trees With Factors

medium array hash map dp sorting

Problem

Given a list of unique integers ≥ 2, count distinct binary trees where each non-leaf node's value equals the product of its two children's values. Each integer in the list may be reused as many times as you want. Return the count modulo 10⁹ + 7.

Inputarr = [2, 4]
Output3
Single-node trees [2], [4], plus 4 with children (2, 2).

def num_factored_binary_trees(arr):
    MOD = 10**9 + 7
    arr.sort()
    dp = {x: 1 for x in arr}
    s = set(arr)
    for x in arr:
        for a in arr:
            if a * a > x:
                break
            if x % a == 0 and (x // a) in s:
                b = x // a
                ways = dp[a] * dp[b]
                if a != b:
                    ways *= 2
                dp[x] = (dp[x] + ways) % MOD
    return sum(dp.values()) % MOD
function numFactoredBinaryTrees(arr) {
  const MOD = 1_000_000_007n;
  arr.sort((a, b) => a - b);
  const dp = new Map();
  for (const x of arr) dp.set(x, 1n);
  const s = new Set(arr);
  for (const x of arr) {
    for (const a of arr) {
      if (a * a > x) break;
      if (x % a === 0 && s.has(x / a)) {
        const b = x / a;
        let ways = dp.get(a) * dp.get(b);
        if (a !== b) ways *= 2n;
        dp.set(x, (dp.get(x) + ways) % MOD);
      }
    }
  }
  let total = 0n;
  for (const v of dp.values()) total = (total + v) % MOD;
  return Number(total);
}
class Solution {
    public int numFactoredBinaryTrees(int[] arr) {
        long MOD = 1_000_000_007L;
        Arrays.sort(arr);
        Map<Integer, Long> dp = new HashMap<>();
        Set<Integer> s = new HashSet<>();
        for (int x : arr) { dp.put(x, 1L); s.add(x); }
        for (int x : arr) {
            for (int a : arr) {
                if ((long)a * a > x) break;
                if (x % a == 0 && s.contains(x / a)) {
                    int b = x / a;
                    long ways = dp.get(a) * dp.get(b) % MOD;
                    if (a != b) ways = ways * 2 % MOD;
                    dp.put(x, (dp.get(x) + ways) % MOD);
                }
            }
        }
        long total = 0;
        for (long v : dp.values()) total = (total + v) % MOD;
        return (int) total;
    }
}
class Solution {
public:
    int numFactoredBinaryTrees(vector<int>& arr) {
        const long MOD = 1'000'000'007L;
        sort(arr.begin(), arr.end());
        unordered_map<int, long> dp;
        unordered_set<int> s;
        for (int x : arr) { dp[x] = 1; s.insert(x); }
        for (int x : arr) {
            for (int a : arr) {
                if ((long)a * a > x) break;
                if (x % a == 0 && s.count(x / a)) {
                    int b = x / a;
                    long ways = dp[a] * dp[b] % MOD;
                    if (a != b) ways = ways * 2 % MOD;
                    dp[x] = (dp[x] + ways) % MOD;
                }
            }
        }
        long total = 0;
        for (auto& kv : dp) total = (total + kv.second) % MOD;
        return (int) total;
    }
};
Time: O(n²) Space: O(n)