1. 程式人生 > 實用技巧 >#分治#洛谷 5502 [JSOI2015]最大公約數

#分治#洛谷 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));
}