2 条题解
-
2
此题重点在于题干说的“原数列尽可能的短”。
为了使还原后的原等差数列最短,首先我们不能再添加比给定数列的最大值更大,或比最小值更小的数,因为这样的数对还原等差数列无必要性反而会使数列更长。
因此,我们添加的数 一定满足 (, 分别表示给定数列最大最小值)
设给定数列长度为 ,排序后数列为
数列中相邻数之差为
因为还原的数列是等差数列,问题可转换为找到一个公差 , 必须满足以下条件才可正确还原:- 对于所有的 ,一定是 的倍数。即 , %
- 在满足条件1的前提下, 尽可能的大。(为了使原数列尽可能的短)
条件1也可表述为 一定是所有 的公因数,条件2指 应尽可能的大,故可得 为所有 的最大公因数。
因此,我们可以使用讲过的 算法快速求出所有 的最大公因数,即公差 。由等差数列求项数公式 求出还原后数列的长度,再使用求和公式 即可得到原数列和。
Code:
#include<iostream> #include<stdio.h> #include<algorithm> using namespace std; long long gcd(long long x, long long y)// gcd函数求最大公约数 { long long z; while(y > 0) { z = x % y; x = y; y = z; } return x; } long long a[100010];// 数组定义在主函数外 int main() { int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%lld", &a[i]); } sort(a, a + n);// 排序a数组 if(a[0] == a[n - 1])// 特判全相等的情况 { printf("%lld", a[0] * n); } else { long long d = a[1] - a[0]; for(int i = 2; i < n; i++) { d = gcd(d, a[i] - a[i - 1]);// 循环计算最大公约数 } long long tn = (a[n - 1] - a[0]) / d + 1;// 计算序列项数 printf("%lld", (a[0] + a[n - 1]) * tn / 2);// 求和 } return 0; }
常见错误原因:
- 未正确使用gcd
- 未特判全相等的特例
- 未开 long long 导致超出范围
信息
- ID
- 954
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 404
- 已通过
- 27
- 上传者