# [823. Binary Trees With Factors](https://leetcode.com/problems/binary-trees-with-factors/) ## 题目 Given an array of unique integers, `arr`, where each integer `arr[i]` is strictly greater than `1`. We make a binary tree using these integers, and each number may be used for any number of times. Each non-leaf node's value should be equal to the product of the values of its children. Return *the number of binary trees we can make*. The answer may be too large so return the answer **modulo** `109 + 7`. **Example 1:** ``` Input: arr = [2,4] Output: 3 Explanation: We can make these trees: [2], [4], [4, 2, 2] ``` **Example 2:** ``` Input: arr = [2,4,5,10] Output: 7 Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2]. ``` **Constraints:** - `1 <= arr.length <= 1000` - `2 <= arr[i] <= 10^9` ## 题目大意 给出一个含有不重复整数元素的数组,每个整数均大于 1。我们用这些整数来构建二叉树,每个整数可以使用任意次数。其中:每个非叶结点的值应等于它的两个子结点的值的乘积。满足条件的二叉树一共有多少个?返回的结果应模除 10 * 9 + 7。 ## 解题思路 - 首先想到的是暴力解法,先排序,然后遍历所有节点,枚举两两乘积为第三个节点值的组合。然后枚举这些组合并构成树。这里计数的时候要注意,左右孩子如果不是对称的,左右子树相互对调又是一组解。但是这个方法超时了。原因是,暴力枚举了很多次重复的节点和组合。优化这里的方法就是把已经计算过的节点放入 `map` 中。这里有 2 层 `map`,第一层 `map` 记忆化的是两两乘积的组合,将父亲节点作为 `key`,左右 2 个孩子作为 `value`。第二层 `map` 记忆化的是以 `root` 为根节点此时二叉树的种类数,`key` 是 `root`,`value` 存的是种类数。这样优化以后,DFS 暴力解法可以 runtime beats 100%。 - 另外一种解法是 DP。定义 `dp[i]` 代表以 `i` 为根节点的树的种类数。dp[i] 初始都是 1,因为所有节点自身可以形成为自身单个节点为 `root` 的树。同样需要先排序。状态转移方程是: $$dp[i] = \sum_{j