一、题目分析
本题要求构造一个包含 n 个元素的数组,同时需要满足三个关键条件:一是数组中的所有元素两两不同;二是数组所有元素的最大公约数为给定的 k;三是在满足前两个条件的基础上,要让数组元素之和尽可能小。最终任务是输出满足这些条件的数组元素之和的最小值。
二、解题思路探讨
- 关于最大公约数条件的思考
既然要求数组所有元素的最大公约数为k,那么可以设想数组中的每个元素都能写成k乘以某个整数的形式。例如,如果k = 3,数组元素可以是3×1、3×2、3×3等等。这样构造出来的数组元素天然就保证了最大公约数是k,满足题目条件中的第二条。 - 满足元素两两不同且和最小的策略分析
为了让数组元素之和尽可能小,同时又要保证元素两两不同,我们可以采用一种比较自然的构造方式,即让数组元素分别为k×1、k×2、k×3、……、k×n。这样的构造方式能保证每个元素都不同(因为乘的系数1到n各不相同),而且按照自然数从小到大的顺序去乘以k,能使得整体的和相对最小。这是基于一种贪心的思想,从小的数开始选取,逐步构建满足条件的数组,期望最终得到的和是最小的。
三、具体解题步骤
-
计算基础自然数序列的和
首先,我们需要计算从1到n这些自然数的和。数学上,计算1 + 2 + 3 + … + n的和有一个简洁的公式,即n * (n + 1) // 2(这里使用//表示整除运算,在很多编程语言中可以这样来获取整数除法的结果)。这个公式的推导可以通过等差数列求和公式得到,首项a₁ = 1,末项aₙ = n,项数为n,根据等差数列求和公式Sₙ = (a₁ + aₙ) * n / 2,代入可得Sₙ = (1 + n) * n / 2,化简后就是n * (n + 1) // 2。我们把这个和记为sum_of_first_n。 -
得到满足条件数组元素之和的最小值
由于前面分析得出数组元素构造为k×1、k×2、k×3、……、k×n,所以整个数组元素之和就是k乘以从1到n这些自然数的和,也就是k * sum_of_first_n。
例如,当 n = 3,k = 1 时:
-
先计算
1 + 2 + 3的和,根据公式可得3 * (3 + 1) // 2 = 6,这就是基础自然数序列的和。 -
再乘以
k(此时k = 1),结果还是6,这就是满足条件的数组元素之和的最小值,对应样例中的输出结果。
又如,当 n = 4,k = 3 时:
- 计算
1 + 2 + 3 + 4的和,通过公式得到4 * (4 + 1) // 2 = 10。 - 然后乘以
k(这里k = 3),得出30,也就是样例中输出的满足条件数组元素之和的最小值。
def solution(n: int, k: int) -> int:
# 计算 1 + 2 + 3 + ... + n 的和
sum_of_first_n = n * (n + 1) // 2
# 乘以 k 得到最终的和
return k * sum_of_first_n
if __name__ == '__main__':
print(solution(n = 3, k = 1) == 6) # 1+2+3 = 6
print(solution(n = 2, k = 2) == 6) # 2+4 = 6
print(solution(n = 4, k = 3) == 30) # 3+6+9+12 = 30
四、复杂度分析
- 时间复杂度
在整个解题过程中,主要进行了一次n * (n + 1) // 2的计算来获取从1到n自然数的和,这个计算操作涉及到简单的乘法和除法运算,其时间复杂度是常数级别的,不随输入的n和k的规模变化而变化,所以整体的时间复杂度为 。 - 空间复杂度
代码中只使用了几个固定的变量(如sum_of_first_n等)来辅助计算,这些变量所占用的空间大小不会随着输入参数n和k的变化而改变,始终保持在常数级别,因此空间复杂度为 。