传送门:计蒜客A1633 蒜头君的数轴
题目描述
题目样例:
样例输入:
4
1 3 7 15
样例输出:
1
思路:
题中说明点坐标乱序排列,那么首先将其排序,并计算相邻两点的间距。要使得数轴最多只有一对点的距离与其他不同且插入的点最少,我们可以尝试忽略某个间距p[i],找出此时其他所有间距的gcd。所有情况中最大的gcd即为最终的目标间距。
预处理前缀gcd(1~n-1)和后缀gcd(n-1 ~1),当忽略某个间距p[i]时,其他所有间距的gcd为gcd(l[i-1],r[i+1]),找出最大的gcd并记录此时需要忽略的间距的下标。
根据最大目标间距计算要插入的点。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=1e5+5;
int arr[MAXN],p[MAXN];
int l[MAXN],r[MAXN];
int gcd(int a,int b)
{
return b==0 ? a:gcd(b,a%b);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
sort(arr,arr+n);// 排序
for(int i=1;i<n;i++)
p[i]=arr[i]-arr[i-1];// 计算相邻点间距
l[0]=0,r[n]=0;// 0与任何数的 gcd是数本身
for(int i=1;i<n;i++)
l[i]=gcd(l[i-1],p[i]);// 前缀 gcd
for(int i=n-1;i>0;i--)
r[i]=gcd(r[i+1],p[i]);// 后缀 gcd
int maxn=0,pos=0;
for(int i=1;i<n;i++)
{
int temp=gcd(l[i-1],r[i+1]);// 计算忽略间距 p[i] 后的 gcd
if(temp>maxn)
{
pos=i; // 忽略间距的下标
maxn=temp;// 最大目标间距
}
}
int ans=0;
for(int i=1;i<n;i++)
if(i!=pos) // 不是被忽略的间距
ans+=p[i]/maxn-1;
printf("%d\n",ans);
return 0;
}