2018 蓝桥杯省赛 B 组模拟赛(五)蒜头君的数轴

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

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

输入格式

输入第一行为一个整数 n(1n105),表示数轴上的点数。

第二行为 n个不重复的整数x1,x2,...,xn(109xi109),表示这些点的坐标,点坐标乱序排列。

输出格式

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

样例输入
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]).  
**************************************************************/  
  
#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;  
}  

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值