今天蒜头君拿到了一个数轴,上边有 nnn 个点,但是蒜头君嫌这根数轴不够优美,想要通过加一些点让它变优美,所谓优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同。
蒜头君想知道,他最少需要加多少个点使这个数轴变优美。
输入格式
输入第一行为一个整数 n(1≤n≤105)n(1 \leq n \leq 10^5)n(1≤n≤105),表示数轴上的点数。
第二行为 nnn 个不重复的整数 x1,x2,...,xn(−109≤xi≤109)x_1,x_2,...,x_n(-10^9 \leq x_i \leq 10^9)x1,x2,...,xn(−109≤xi≤109),表示这些点的坐标,点坐标乱序排列。
输出格式
输出一行,为一个整数,表示蒜头君最少需要加多少个点使这个数轴变优美。
样例输入
4 1 3 7 15
样例输出
1
#include<cstdio>
#include<cstring>
#include<algorithm>
#define bug(x) printf("%d***\n",x)
#define lbug(x) printf("%lld***\n",x)
typedef long long ll;
using namespace std;
/*
自己的思维还是比较死
一看见删掉一个,我们就想从头到尾,
但是不要忘了预处理这个环节
如果我们可以预处理一段区间的话
我们就可以用2*N换得N*N的效果
实在是巧妙
*/
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
const int maxn=1e5+10;
ll val[maxn],inter[maxn];
ll gcd1[maxn],gcd2[maxn];
int n;
void get_gcd(){
gcd1[0]=inter[2];
gcd1[1]=inter[1];
for(int i=2;i<n;i++){
gcd1[i]=gcd(inter[i],gcd1[i-1]);
}
gcd2[n]=inter[n-2];
gcd2[n-1]=inter[n-1];
for(int i=n-2;i>=1;i--){
gcd2[i]=gcd(inter[i],gcd2[i+1]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&val[i]);
}
if(n<=3){
printf("0\n");
return 0;
}
sort(val+1,val+n+1);
for(int i=1;i<n;i++){
inter[i]=val[i+1]-val[i];
}
get_gcd();
ll ans=1,pos=1;
for(int i=1;i<n;i++){
ll tmp=gcd(gcd1[i-1],gcd2[i+1]);
if(tmp>ans){
ans=tmp;
pos=i;
}
}
ll ed=0;
for(int i=1;i<n;i++){
if(i==pos) continue;
ed+=(inter[i]/ans -1);
}
//lbug(ans);
// bug(pos);
printf("%lld\n",ed);
return 0;
}