今天蒜头君拿到了一个数轴,上边有 n个点,但是蒜头君嫌这根数轴不够优美,想要通过加一些点让它变优美,所谓优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同。
蒜头君想知道,他最少需要加多少个点使这个数轴变优美。
输入格式
输入第一行为一个整数 (1≤n≤100000),表示数轴上的点数。
第二行为 nnn 个不重复的整数 x1,x2,...,xn(−1000000000≤xi≤1000000000)表示这些点的坐标,点坐标乱序排列。
输出格式
输出一行,为一个整数,表示蒜头君最少需要加多少个点使这个数轴变优美。
样例输入
4 1 3 7 15
样例输出复制
1
题意:刚开始没有理解到 “优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同” 这句话是个什么意思;
其实很简单,就是一对点不同,其余个点的距离相同;
基本思路:就是把不同的那对点的距离不考虑;求其他段的的一个最大公约数,由于不同的距离可以是两端的任意一段,所以我们需要求一个前缀最大公约数,以及后缀最大公约数;然后在枚举去除中间某一段的最大公约数;最后找到最大公约数,并把去除的那个段标记,然后用每段距离除最大公约数,求和,即是需要加的点的个数。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=100005;
int a[maxn];
int l[maxn],r[maxn],pre[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
int sum=0;
for(int i=1; i<n; i++)
pre[i-1]=a[i]-a[i-1];
l[0]=pre[0];
r[n-1]=pre[n-1];
for(int i=1; i<n; i++)///从前往后求DCD
l[i]=__gcd(l[i-1],pre[i]);
for(int i=n-2; i>=0; i--)///从后往前求GCD
r[i]=__gcd(r[i+1],pre[i]);
int mx=0;
int pos=0;
for(int i=0; i<n; i++)
{
int te=__gcd(l[i-1],r[i+1]);
// cout<<l[i-1]<<" "<<r[i+1]<<" "<<te<<endl;
if(te>=mx)///找到距离差最大公因数
{
mx=te;
pos=i;
}
}
for(int i=0; i<n-1; i++)
{
if(i!=pos)
sum+=pre[i]/mx-1;///每一段需要添加多少个点
}
cout<<sum<<endl;
return 0;
}