📜  a + b + c = n 的非负积分解的数量(1)

📅  最后修改于: 2023-12-03 15:13:14.458000             🧑  作者: Mango

题目概述

给定一个正整数 $n$,求出满足 $a+b+c=n$ 且 $a,b,c$ 均为非负整数的三元组 $(a,b,c)$ 的数量。

解题思路

可以使用搜索或者数学计算的方法解决此问题。

方法一:搜索

可以使用深度优先搜索(DFS)来解决此问题。从 $a,b,c$ 均为 $0$ 的状态出发,每次增加 $a,b,c$ 中的其中一个数,并更新已有的两个数,继续向下搜索。当非负整数和为 $n$ 时,计数器加 $1$。最后返回计数器的值即为答案。

def search(n):
    cnt = 0
    
    def dfs(a, b, c):
        nonlocal cnt
        if a + b + c == n:
            cnt += 1
            return
        if a < n:
            dfs(a + 1, b, c)
        if b < n:
            dfs(a, b + 1, c)
        if c < n:
            dfs(a, b, c + 1)
    
    dfs(0, 0, 0)
    return cnt

时间复杂度:$O(n^3)$。

方法二:数学计算

显然,在 $a,b,c$ 都为非负整数的约束下,满足 $a+b+c=n$ 的三元组 $(a,b,c)$ 的数量等价于在 $a'+b'+c'=n+3$ 的条件下,$a',b',c'$ 为非负整数的三元组 $(a',b',c')$ 的数量。然后,可以使用「插板法」或者组合数计算的方法计算出该数量。

插板法

在 $a'+b'+c'=n+3$ 的等式中插入 $2$ 个分隔线,将 $n+3$ 个物品分成 $3$ 组,每组至少有 $1$ 个物品。每个物品代表 $1$。每个分隔线代表一个组的结尾。则可以得到一种映射关系,将问题转化为将 $n+3$ 个物品($n$ 个 $1$ 和 $3$ 个分隔线)放入 $3$ 个无区别的盒子中。

假设有 $n+3$ 个球,对于其中 $3$ 个不同的球,选一个刚好表示为末尾的盒子的球,可以得到 $\binom{3}{1}$ 种选法。然后,将剩余的 $n$ 个球放入 $3$ 个无区别的盒子中,可以得到 $\binom{n+3-1}{3-1}$ 种选法。综上,满足约束条件的三元组数量为 $\binom{3}{1}\binom{n+3-1}{3-1}=\frac{(n+1)(n+2)}{2}$。

组合数计算

可以使用组合数的方式计算出答案。在 $n+3$ 个位置间选择 $3$ 个位置插入分隔线,则有 $\binom{n+3}{3}$ 种选法。根据组合数的对称性质,其中有 $\binom{3}{1}$ 种选法满足一个分隔线在前两个位置间,一个分隔线在后两个位置间。因此,满足约束条件的三元组数量为 $\binom{n+3}{3}\cdot\binom{3}{1}=\frac{(n+1)(n+2)}{2}$。

import math

def combination(n, k):
    return math.factorial(n) // (math.factorial(k) * math.factorial(n - k))

def math_calculation(n):
    return combination(n + 3, 3) * 3

print(math_calculation(5))  # 36

时间复杂度:$O(1)$。

总结

以上就是两种解决该问题的方法。搜索的时间复杂度虽然为 $O(n^3)$,但是可以通过记忆化优化。数学计算的时间复杂度为 $O(1)$,但是需要具备一定的数学运算能力。在实际应用中,也可以根据问题规模和时间限制选择相应的方法。