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