[BZOJ 4488][Jsoi2015]最大公约数

传送门

不知谁说过一句名句,我们要学会复杂度分析

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i=a;i<=b;++i)
 4 #define fd(i,a,b) for(int i=a;i>=b;--i)
 5 const int maxn=100010;
 6 typedef long long ll;
 7 inline ll gi() {
 8     ll x=0; char o; bool f=true; for(;!isdigit(o=getchar());) if(o=='-')f=false;
 9     for(;isdigit(o);o=getchar()) x=(x<<1)+(x<<3)+(o&15); return f?x:~x+1;
10 }
11 ll ans,a[maxn],pre[maxn<<2][20];
12 int n;
13 ll gcd(ll x,ll y){return x?gcd(y%x,x):y;}
14 ll gt(int s,int t) {
15     ll ret=a[s];
16     fd(i,18,0) if(s+(1<<i)-1<=t)
17         ret=gcd(ret,pre[s][i]),s=s+(1<<i);
18     return ret;
19 }
20 int Find(int l,int r,int s,ll v) {
21     int ret=l;
22     while( l<=r) {
23         int mid=l+r>>1;
24         if(gt(s,mid)>=v) ret=mid,l=mid+1;
25         else r=mid-1;
26     }
27     return ret;
28 }
29 int main() {
30 #ifndef ONLINE_JUDGE
31     freopen("3.in","r",stdin);
32 #endif
33     scanf("%d",&n); rep(i,1,n) a[i]=pre[i][0]=gi();
34     rep(k,1,18) rep(i,1,n) 
35         pre[i][k]=gcd(pre[i+(1<<k-1)][k-1],pre[i][k-1]);
37     rep(i,1,n) {
38         int L=i;
39         while(L<=n) {
40             ll val=gt(i,L); int ed=Find(i,n,i,val);
41             ans=max(ans,1LL*(ed-i+1)*val); L=ed+1;
43         }
44     }
45     printf("%lld\n",ans);
46     return 0;
47 }

猜你喜欢

转载自www.cnblogs.com/miecoku/p/9764273.html
今日推荐