题目来源:2019,省赛
知识点:等差数列,最大公约数 (gcd)
输入输出样例
示例
- 输入
5
2 6 4 10 20
- 输出
10
- 样例说明: 包含 2、6、4、10、20 的最短的等差数列是 2、4、6、8、10、12、14、16、 18、20。
题目分析
首先肯定是对数组进行排序。如果要等差数列的项最少,公差应该最大。本题容易陷入一个误区是:将排序后相邻两个数之间的最小差值作为公差。这显然是不对的,可以看下面的一个特例。
因此,真正的公差应该是所有相邻数之间的差值再求最大公约数。上例中 2 与 3 的最大公约数为 1,所以该等差数列的公差就是 1。在知道最小和最大的等差数列的元素时,项数的求法为: ( m a x − m i n ) / d + 1 (max-min)/d+1 (max−min)/d+1。
另外,还有一种特殊情况:公差为0。此时的等差数列所有元素相等,项数就是一开始输入的 n。
问题
每次涉及求gcd、lcm的问题时,手动写函数比较麻烦。对于c++来说,可以使用algorithm里面的函数来直接求解,十分方便。
#include <algorithm>
int main() {
int a = 2;
int b = 3;
cout << __gcd(a, b) << endl;
cout << a * b / __gcd(a, b) <<endl; //lcm
return 0;
}
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
long n;
long *weight;
cin >> n;
weight = new long[n]();
for(long i = 0; i < n; i++) {
cin >> weight[i];
}
sort(weight, weight + n);
long* dif = new long[n]();
bool flag = false;
for(long i = 0; i < n - 1; i++) {
dif[i] = weight[i + 1] - weight[i];
if(dif[i] == 0) {
flag = true;
break;
}
}
if(flag) {
cout << n << endl;
return 0;
}
long gcd = __gcd(dif[0], dif[1]);
for(long i = 2; i < n - 1; i++) {
gcd = __gcd(dif[i], gcd);
}
long num = (weight[n - 1] - weight[0]) / gcd + 1;
cout << num << endl;
delete[] weight;
delete[] dif;
return 0;
}