转自:https://blog.csdn.net/sugarbliss/article/details/79710006
熊的博客
题目:
今天蒜头君拿到了一个数轴,上边有 nn 个点,但是蒜头君嫌这根数轴不够优美,想要通过加一些点让它变优美,所谓优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同。
蒜头君想知道,他最少需要加多少个点使这个数轴变优美。
输入格式
输入第一行为一个整数 n(1≤n≤105),表示数轴上的点数。
第二行为 n个不重复的整数x1,x2,...,xn(−109≤xi≤109),表示这些点的坐标,点坐标乱序排列。
输出格式
输出一行,为一个整数,表示蒜头君最少需要加多少个点使这个数轴变优美。
样例输入
4 1 3 7 15
样例输出
1
主要思路是求:最大公约数。
n个数,互不相同,则求相邻两点距离,共有n-1个距离。
题目允许最多有一对点距离与其他不同,因此对于n-1个距离,我们
都要考虑到,因此要对n-1个距离追个删去,对剩余n-2个距离求共同
的最大公约数。为了求得这个最大公约数。
则解法如下:
1.如果n<=3,则不需要考虑题中操作就满足题目要求,答案为0.
2.除情况1外的其他情况。
设置gcd1[i]:表示前i个距离求得的公共最大公约数。
设置gcd2[i],表示后i个距离求得的公共最大公约数。
则考虑逐个删除某个距离,假设当前删除第i个距离。
若i = 1,即删除第一个距离,则需要后n-2个距离的最大公约数,即gcd2[n-2].
若i = n-1,即删除最后一个距离,则需要前n-2个距离的最大公约数,即gcd1[n-2].
若i > 1 && i < n-1,则需要前i-1个距离的最大公约数和后n-1-i个距离的最大公约数
和在一起求出最大公约数。即gcd(gcd1[i-1],gcd2[n-i-1]).
n个数,互不相同,则求相邻两点距离,共有n-1个距离。
题目允许最多有一对点距离与其他不同,因此对于n-1个距离,我们
都要考虑到,因此要对n-1个距离追个删去,对剩余n-2个距离求共同
的最大公约数。为了求得这个最大公约数。
则解法如下:
1.如果n<=3,则不需要考虑题中操作就满足题目要求,答案为0.
2.除情况1外的其他情况。
设置gcd1[i]:表示前i个距离求得的公共最大公约数。
设置gcd2[i],表示后i个距离求得的公共最大公约数。
则考虑逐个删除某个距离,假设当前删除第i个距离。
若i = 1,即删除第一个距离,则需要后n-2个距离的最大公约数,即gcd2[n-2].
若i = n-1,即删除最后一个距离,则需要前n-2个距离的最大公约数,即gcd1[n-2].
若i > 1 && i < n-1,则需要前i-1个距离的最大公约数和后n-1-i个距离的最大公约数
和在一起求出最大公约数。即gcd(gcd1[i-1],gcd2[n-i-1]).
具体代码如下:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
int gcd1[maxn]; //gcd1[i]是前i个距离的gcd
int gcd2[maxn]; //gcd2[i]是后i个距离的gcd
int arr[maxn];
long long dist[maxn];
int gcd(int a,int b) {
if(b==0) return a;
else return gcd(b,a%b);
}
int main() {
int n;
long long sum;
while(~scanf("%d",&n)) {
for(int i = 0; i < n; i++) {
scanf("%d",&arr[i]);
}
if(n<=3) {
printf("0\n");
continue;
}
sort(arr,arr+n);
sum = 0;
for(int i = 1; i < n; i++) {
dist[i] = arr[i]-arr[i-1];
sum += dist[i];
}
int d = dist[0];
for(int i = 1; i <= n-1; i++) {
d = gcd(d,dist[i]);
gcd1[i] = d;
}
d = dist[n-1];
for(int i = 1; i <= n-1; i++) {
d = gcd(d,dist[n-i]);
gcd2[i] = d;
}
int Min = 0x3f3f3f3f;
int temp;
//枚举删除每一个区间
for(int i = 1; i <= n-1; i++) {
if(i == 1) {
temp = (sum-dist[i])/gcd2[n-2];
}
else if(i == n-1) {
temp = (sum-dist[i])/gcd1[n-2];
}
else {
temp = (sum-dist[i])/gcd(gcd1[i-1],gcd2[n-1-i]);
}
Min = min(Min,temp-(n-2));
}
printf("%d\n",Min);
}
return 0;
}