原理
该程序通过迭代计算相邻元素的最小公倍数(LCM),逐步将数组中的元素合并,最终得到整个数组的最小公倍数。具体原理如下:
- LCM 的传递性
LCM 满足结合律,即lcm(a, b, c) = lcm(lcm(a, b), c)
。程序通过逐个合并相邻元素,最终得到整个数组的 LCM。 - 逐步覆盖数组
每次计算当前元素与下一个元素的 LCM,并将结果覆盖到下一个元素的位置。最终最后一个元素即为整个数组的 LCM。
步骤
- 输入处理
读取整数n
和包含n
个元素的数组A
。 - 迭代计算 LCM
从第一个元素开始,依次计算当前元素与下一个元素的 LCM,并将结果覆盖到下一个元素的位置。 - 输出结果
数组的最后一个元素即为整个数组的 LCM。
图示法示例(输入:[2, 3, 4]
)
初始数组: [2, 3, 4]
步骤1: 计算 lcm(2,3)=6 → 数组变为 [2, 6, 4]
步骤2: 计算 lcm(6,4)=12 → 数组变为 [2, 6, 12]
输出: 12
代码程序及关键行注释
#include <iostream>
#include <vector>
using namespace std;
// 计算最大公约数(GCD)
int gcd(int a, int b) {
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
// 计算最小公倍数(LCM)
int lcm(int a, int b) {
if (a == 0 || b == 0) return 0; // 处理边界情况
return (a / gcd(a, b)) * b; // 公式:LCM(a,b) = a*b / GCD(a,b)
}
int main() {
int n;
cin >> n;
vector<int> A(n);
for (int i = 0; i < n; i++) {
cin >> A[i];
}
int i = 0;
while (i < n - 1) { // 遍历到倒数第二个元素
A[i + 1] = lcm(A[i], A[i + 1]); // 将后一个元素替换为当前LCM
i++;
}
cout << A[n - 1] << endl; // 输出最后一个元素(即最终LCM)
return 0;
}
时间复杂度
- 单次 LCM 计算
每次 LCM 计算的时间复杂度为O(log(min(a, b)))
,其中a
和b
为参与计算的两个数。 - 总时间复杂度
数组需要遍历n-1
次,总时间复杂度为O(n * log M)
,其中M
为数组中的最大值。
总结
- 核心思想
利用 LCM 的结合律,通过迭代合并相邻元素,逐步计算整个数组的 LCM。 - 优点
代码简洁,逻辑清晰,适用于小规模数据。 - 潜在问题
若数组元素较大或较多,LCM 值可能超出整数范围(需根据题目约束判断)。 - 适用场景
适用于输入规模较小且数值范围可控的场景。若数值过大,需改用大数处理或优化算法。