[JSOI2015]最大公约数
题意:
给一个序列a[1],a[2],a[3]...a[n],求其中连续的子序列A[L],A[L+1],...,A[R],使其权值 W(L,R)=(R-L+1)×gcd(A[L],...,A[R])最大。
给一个序列a[1],a[2],a[3]...a[n],求其中连续的子序列A[L],A[L+1],...,A[R],使其权值 W(L,R)=(R-L+1)×gcd(A[L],...,A[R])最大。
输入格式
输入一行包含一个正整数n
接下来一行,包含N个正整数,
表示序列A_i
输入一行包含一个正整数n
接下来一行,包含N个正整数,
表示序列A_i
输出格式
输出文件包含一行一个正整数,表示权值最大的子序列的权值。
输出文件包含一行一个正整数,表示权值最大的子序列的权值。
输入 #1
5
30 60 20 20 20
5
30 60 20 20 20
输出 #1
80
80
说明/提示
1≤Ai≤10^12,1≤N≤100000
1≤Ai≤10^12,1≤N≤100000
可知一个数的质因数个数最多为logai次
那么对ai与其他a取gcd,最多有logai个值
那么记录下j的最左端点,使任意gcd(a_(j+k),...a_i)相同
算上求gcd,复杂度为O(nlog^2n)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 int n,cnt[100001]; 8 lol Gcd[100001][30]; 9 int lst[100001][30]; 10 lol a[100001]; 11 lol ans; 12 lol gcd(lol a,lol b) 13 { 14 if (!b) return a; 15 return gcd(b,a%b); 16 } 17 lol max(lol a,lol b) 18 { 19 if (a>b) return a; 20 return b; 21 } 22 int main() 23 {int i,j; 24 cin>>n; 25 for (i=1;i<=n;i++) 26 scanf("%lld",&a[i]); 27 for (i=1;i<=n;i++) 28 { 29 cnt[i]=1; 30 Gcd[i][cnt[i]]=a[i]; 31 lst[i][cnt[i]]=i; 32 ans=max(ans,a[i]); 33 for (j=1;j<=cnt[i-1];j++) 34 { 35 cnt[i]++; 36 Gcd[i][cnt[i]]=gcd(Gcd[i][cnt[i]-1],Gcd[i-1][j]); 37 lst[i][cnt[i]]=lst[i-1][j]; 38 ans=max(ans,(lol)(i-lst[i][cnt[i]]+1)*Gcd[i][cnt[i]]); 39 if (Gcd[i][cnt[i]]==Gcd[i][cnt[i]-1]) 40 { 41 cnt[i]--; 42 lst[i][cnt[i]]=lst[i-1][j]; 43 } 44 } 45 } 46 cout<<ans; 47 }