#分治#洛谷 5502 [JSOI2015]最大公约数

题目


分析

又是一道思维题,考虑用分治,选取左边或右边的基准尽量扩展长度,时间复杂度\(O(nlog_2n)\)


代码

#include <cstdio>
#include <cctype>
#define rr register
typedef long long lll;
lll n,a[1000011];
inline lll iut(){
    rr lll ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline lll max(lll a,lll b){return a>b?a:b;}
inline lll gcd(lll a,lll b){return b?gcd(b,a%b):a;}
inline lll dfs(int l,int r){
    if (l==r) return a[l];
    rr int mid=(l+r)>>1,L=mid,R=mid+1;
    rr lll now=gcd(a[mid],a[mid+1]),ans=now<<1;
    ans=max(ans,max(dfs(l,mid),dfs(mid+1,r)));
    while (L>=l&&R<r){
        now=gcd(now,a[++R]);
        for (;L>=l&&!(a[L]%now);--L); ++L;
        for (;R<=r&&!(a[R]%now);++R); --R;
        ans=max(ans,now*(R-L+1));
    }
    now=gcd(a[mid],a[mid+1]),L=mid,R=mid+1;
    while (L>l&&R<=r){
        now=gcd(now,a[--L]);
        for (;L>=l&&!(a[L]%now);--L); ++L;
        for (;R<=r&&!(a[R]%now);++R); --R;
        ans=max(ans,now*(R-L+1));
    }
    return ans;
}
signed main(){
    n=iut();
    for (rr int i=1;i<=n;++i) a[i]=iut();
    return !printf("%lld",dfs(1,n));
}
posted @ 2020-08-09 22:04  lemondinosaur  阅读(188)  评论(0编辑  收藏  举报