• UVA1642 魔法GCD Magical GCD [gcd, 双向链表]


    Magical GCDMagical GCD

    给一个长度为 n(n100000)n(n≤100000) 的数列(每个数 a[i]1012a[i]≤10^{12} ),找到一个连续子序列使得子序列的公约数与长度的乘积最大,求这个最大值 .


    color{blue}{最初想法}

    找规律发现好像 左端点固定, gcdgcd*长度 随着 长度 增加而单调递增, 于是线段树查找区间和, O(NlogN)O(NlogN) 迎来 50pts50pts.
    这是错的 . 早知道多打几组数据了 .


    color{red}{正解部分}

    若固定一个数的集合, 不断地往里面加数, 整个集合的 gcdgcd 只可能是 单调不增 的, 且每次减少都 至少减少为原来的 12frac{1}{2} .

    枚举右端点 rr, 左端点ll从左向右移动, 可以发现 gcd[l,r]gcd[l, r] 是成块状连续的, 在 gcdgcd 相同的前提下, 显然取左端点最优,
    所以对每个右端点, 只需用 双向链表 维护, 即可实现 只需枚举 log(ai)log (a_i) 个左端点 去更新答案 .

    时间复杂度 O(Nlog(ai))O(Nlog(a_i))


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    const int maxn = 100005;
    
    int N;
    ll Ans;
    ll A[maxn];
    ll gcd[maxn];
    int pre[maxn];
    int nxt[maxn];
    
    ll Gcd(ll a, ll b){ return !b?a:Gcd(b, a%b); }
    
    void Work(){
            Ans = 0;
            scanf("%d", &N);
            for(reg int i = 1; i <= N; i ++){
                    scanf("%lld", &A[i]);
                    pre[i] = i-1, nxt[i] = i+1;
                    gcd[i] = A[i];
            }
            nxt[0] = 1;
            for(reg int i = 1; i <= N; i ++)
                    for(reg int j = nxt[0]; j <= i; j = nxt[j]){
                            int &pre_1 = pre[j], &pre_2 = pre[pre_1];
                            gcd[j] = Gcd(gcd[j], A[i]);
                            if(gcd[j] == gcd[pre_1]){
                                    nxt[pre_2] = j;
                                    pre[j] = pre_2;
                            }
                            Ans = std::max(Ans, 1ll*(i-pre_1)*gcd[j]);
                    }
            printf("%lld
    ", Ans);
    }
    
    int main(){
            int T;
            scanf("%d", &T);
            while(T --) Work();
            return 0;
    }
    
  • 相关阅读:
    docker 会这些也够
    Linux 学会这些基本可以啦
    xxxxxxxxx
    Angular
    mongo
    node
    git clone 解决Permission Denied (publickey)问题
    vue项目如何刷新当前页面
    vue——动态路由以及地址传参
    vue 单页应用点击某个链接,跳转到新页面的方式
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822539.html
Copyright © 2020-2023  润新知