码迷,mamicode.com
首页 > 其他好文 > 详细

计蒜客 蒜头君的数轴

时间:2018-03-27 20:51:45      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:can   ==   ons   tin   pos   pac   using   公约数   color   

不考虑某个区间,其他区间必须距离相等,也就是要划分为距离为最大公约数。

那么如何快速求解任意$n-1$个区间的最大公约数?用l[i]表示前i个数的最大公约数,r[i]表示后$(n-i)$个区间的最大公倍数,删除区间i之后剩余的$n-1$个区间的最大公约数就是$gcd(l[i-1], r[i+1])$


 

AC代码

#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 5;
int x[maxn], dis[maxn];
int l[maxn], r[maxn];

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a%b);
}

int main() {
    int n;
    while(scanf("%d", &n) == 1) {
        for(int i = 0; i < n; i++) {
            scanf("%d", &x[i]);
        }
        if(n <= 3) {
            printf("0\n");
            continue;
        }
        sort(x, x+n);
        LL sum_dis = 0;
        for(int i = 1; i < n; i++) {
            dis[i-1] = x[i] - x[i-1];
            sum_dis += dis[i-1];
        }
        LL ans = 1e18;
        n -= 1;
        l[0] = dis[0];
        for(int i = 1; i < n; i++) {
            l[i] = gcd(l[i-1], dis[i]);
        }
        r[n-1] = dis[n-1];
        for(int i = n-2; i >= 0; i--) {
            r[i] = gcd(r[i+1], dis[i]);
        }
        //删除最左端距离
        ans = min(ans, (sum_dis-dis[0])/r[1] - (n-1));
        //删除最右端距离
        ans = min(ans, (sum_dis-dis[n-1])/l[n-2] - (n-1));
        //删除[1,n-2]
        for(int i = 1; i <= n-2; i++) {
            ans = min(ans, (sum_dis - dis[i])/gcd(l[i-1], r[i+1]) - (n-1));
        }
        printf("%lld\n", ans);
    } 
    return 0;
}

如有不当之处欢迎指出!

计蒜客 蒜头君的数轴

标签:can   ==   ons   tin   pos   pac   using   公约数   color   

原文地址:https://www.cnblogs.com/flyawayl/p/8659044.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!