14.数组元素之和最小化 | 豆包MarsCode AI刷题

106 阅读1分钟

问题描述

小C想构造一个满足特定条件的数组,要求如下:

  1. 数组中的所有元素两两不同。
  2. 数组所有元素的最大公约数为 k
  3. 数组元素之和尽可能小。

任务是输出该数组元素之和的最小值。

测试样例

样例 1

输入n = 3 ,k = 1

输出6

样例 2

输入n = 2 ,k = 2

输出6

样例 3

输入n = 4 ,k = 3

输出30

解题思路分析

1. 条件分解

为了满足题目要求:

  • 元素的最大公约数为 kk:说明数组中的每个元素都必须是 kk 的倍数。例如,如果 k=2k = 2,数组可能是 [2,4,6,][2, 4, 6, \ldots]
  • 元素两两不同:要求所有元素不重复,且必须选择尽可能小的值。
  • 元素和尽可能小:为了最小化总和,需要选择数组的 nn 个最小元素。

2. 解法设计

结合以上分析,可以设计如下解法:

  1. kk 开始,依次选取 kk2k2k3k3k、...、nknk 作为数组的元素。这些元素既是 kk 的倍数,又是递增的,保证了两两不同。

  2. 求和:这些元素的和为: k+2k+3k++nk=k(1+2+3++n)k + 2k + 3k + \ldots + nk = k \cdot (1 + 2 + 3 + \ldots + n)

    等差数列求和公式: 1+2+3++n=n(n+1)21 + 2 + 3 + \ldots + n = \frac{n \cdot (n + 1)}{2}

    所以总和为: kn(n+1)2k \cdot \frac{n \cdot (n + 1)}{2}

3. 计算最小和

通过以上公式,可以直接计算出数组元素之和的最小值。

代码实现

以下是代码实现:

def solution(n: int, k: int) -> int:
    # 使用公式直接计算
    return k * (n * (n + 1)) // 2

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)

知识点总结

1. 最大公约数的性质

  • 如果数组中所有元素的最大公约数为 kk,则每个元素必须是 kk 的倍数。
  • 将问题转化为操作倍数关系时,可以有效减少不必要的复杂性。

2. 等差数列求和公式

S=n(n+1)2S = \frac{n \cdot (n + 1)}{2}

3. 数学与编程结合

这种题目利用数学公式可以快速推导出结果,避免了复杂的遍历和冗余计算。实现过程中,核心是将数学推导的结果直接转化为程序逻辑。

思考与优化

1. 时间复杂度分析

由于仅涉及公式计算,代码的时间复杂度为 O(1)O(1)

2. 边界条件

需要注意以下边界情况:

  • n=1n = 1:只有一个元素 kk,总和即为 kk
  • k=1k = 1:数组为 [1,2,3,,n][1, 2, 3, \ldots, n],总和为普通的等差数列求和。
  • 较大 nnkk:由于公式直接计算,能够处理非常大的输入。

3. 通用性扩展

如果增加其他限制条件(例如数组中的某些值不能被选取),问题可能变得更加复杂,需要额外设计方案。但当前问题的数学性质使得解法简洁优雅。