• 计蒜客


    我感觉出的很好的一道题,首先不难想到(其实我刚开始没想到),加点的个数就是找已有点两两形成区间的gcd,那么问题就出在了复杂度上,每次循环哪个区间不要复杂度过高,所以运用正反两次前缀和(?好像不能这么叫)预处理一下就可以O(n)搞定了,说一下有一个让我找了一年的bug吧,我把ans的初始值设的太小,导致WA,最后改成了2147483645之后就快乐AC了

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 100010;
    int a[N], f[N], d[N];
    int gcd(int a, int b) {
        if (a < b)    swap(a, b);    
        return (a % b == 0) ? b : gcd(b, a % b);
    }
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        sort(a, a + n);
        int sum = a[n - 1] - a[0];
        f[1] = a[1] - a[0];
        for (int i = 2; i < n; i++)
            f[i] = gcd(a[i] - a[i - 1], f[i - 1]);
        d[n - 2] = a[n - 1] - a[n - 2];
        for (int i = n - 3; i >= 0; i--)
            d[i] = gcd(a[i + 1] - a[i], d[i + 1]);
        int ans = 2147483645;
        ans = min(ans, (sum - a[1] + a[0]) / d[1] + 2 - n);
        ans = min(ans, (sum - a[n - 1] + a[n - 2]) / f[n - 2] + 2 - n);
        for (int i = 1; i < n - 2; i++) {
            ans = min((sum - (a[i + 1] - a[i])) / gcd(f[i], d[i + 1]) + 2 - n, ans);
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    sscanf功能详解(转)
    String to Integer (atoi)
    Reverse Words in a String
    在一个字符串中寻找某个字串
    回文数
    Two Sum
    java 判断牌型?
    股票的最大利润
    队列的最大值
    加密和解密例子
  • 原文地址:https://www.cnblogs.com/cminus/p/11991683.html
Copyright © 2020-2023  润新知