计蒜客 蒜头君的数轴

Posted flyawayl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 蒜头君的数轴相关的知识,希望对你有一定的参考价值。

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

那么如何快速求解任意$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;
}

如有不当之处欢迎指出!

以上是关于计蒜客 蒜头君的数轴的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客习题 蒜头君的猜想(埃氏筛)

61计蒜客 动态规划基础 蒜头君的城堡之旅

计蒜客D2T2 蒜头君的排序(动态维护树状数组)

复习---归并排序求逆序对--计蒜客2017noip模拟赛二--蒜头君的排序

计蒜客模拟赛D1T2 蒜头君的树:树上节点之间最短距离和

计蒜客--蒜头君开公司