程序设计:蒜头君的数轴

今天蒜头君拿到了一个数轴,上边有 nnn 个点,但是蒜头君嫌这根数轴不够优美,想要通过加一些点让它变优美,所谓优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同。

蒜头君想知道,他最少需要加多少个点使这个数轴变优美。

输入格式

输入第一行为一个整数 n(1≤n≤105)n(1 \leq n \leq 10^5)n(1n105),表示数轴上的点数。

第二行为 nnn 个不重复的整数 x1,x2,...,xn(−109≤xi≤109)x_1,x_2,...,x_n(-10^9 \leq x_i \leq 10^9)x1,x2,...,xn(109xi109),表示这些点的坐标,点坐标乱序排列。

输出格式

输出一行,为一个整数,表示蒜头君最少需要加多少个点使这个数轴变优美。

样例输入
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值