问题描述回顾
我们需要构造一个包含 n 个元素的数组,这些元素需要满足以下条件:
- 数组中的所有元素两两不同。
- 数组所有元素的最大公约数(Greatest Common Divisor, GCD)为 k。
- 数组元素之和尽可能小。
解决思路
为了使数组的元素之和最小,我们应该选择最小的 n 个数,这些数都必须能被 k 整除。最直接的选择是从 k 开始,每次递增 k 的倍数,直到选择了 n 个数为止。也就是说,选择的数列为:。
数学推导
设所求的数组元素之和为 (S),则有:
提取公因数 (k):
接下来,我们需要计算括号内的部分 (1 + 2 + 3 + \ldots + n)。这是一个等差数列的求和问题。等差数列求和公式为:
其中:
- 是前 n 项的和。
- 是首项。
- 是第 n 项。
- 是项数。
在我们的例子中,首项 ,末项 ,项数 也是 n。将这些值代入等差数列求和公式:
因此,原问题中的 (S) 可以写成:
为什么选择 k×ik×i 形式的数?
选择 形式的数有几个原因:
- 保证最大公约数为 k:每个数 都能被 k 整除,因此这些数的最大公约数必然是 k。
- 确保元素不同:由于 i 从 1 到 n 依次取值,每个 都是不同的,从而保证了数组中的所有元素两两不同。
- 最小化元素之和:选择最小的 n 个 形式的数可以确保数组元素之和最小。因为随着 i 的增加, 也在增加,所以我们从小到大选择前 n 个这样的数可以保证和最小。
Python 实现
根据上面的推导,我们可以很容易地用 Python 编写一个函数来计算 (S):
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)
代码解释
-
函数定义:
min_sum_of_array(n, k):定义了一个函数,接受两个参数n和k,分别代表数组的长度和数组中所有元素的最大公约数。
-
计算数组元素之和:
S = k * (n * (n + 1)) // 2:根据前面推导的公式,计算数组元素之和。这里使用了整数除法//来确保结果是一个整数,因为题目中提到的所有输入都是整数,所以最终的结果也应该是一个整数。
-
返回结果:
return S:返回计算得到的数组元素之和的最小值。
测试样例解释
-
样例1:
n = 3, k = 1- 数组元素为:1, 2, 3
- 元素之和:$1 + 2 + 3 = 6#
- 按照公式计算:(S = 1 \times \frac{3(3+1)}{2} = 1 \times \frac{12}{2} = 6)
-
样例2:
n = 2, k = 2- 数组元素为:2, 4
- 元素之和:
- 按照公式计算:
-
样例3:
n = 4, k = 3- 数组元素为:3, 6, 9, 12
- 元素之和:
- 按照公式计算:
通过上述详细解释和代码实现,我们可以高效地计算出满足条件的数组元素之和的最小值,而无需实际生成和处理整个数组。