您的位置:首页 > 其它

bzoj 4052: [Cerc2013]Magical GCD

2016-09-28 18:16 246 查看
4052: [Cerc2013]Magical GCD

Time Limit: 10 Sec Memory Limit: 128 MB

Submit: 444 Solved: 187

[Submit][Status][Discuss]

Description

给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12。

求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大。

Input

Output

Sample Input

1

5

30 60 20 20 20

Sample Output

80

【分析】

枚举右端点,左端点从枚举点往左扫,这样的话可以得知gcd单调不增。于是用单调栈维护gcd相同时左端点的最小值。

【代码】

//bzoj 4052 [Cerc2013]Magical GCD
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=1e5+5;
ll n,T,tp,jtp;
ll a[mxn],s[mxn],g[mxn],ss[mxn],gg[mxn];
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline ll gcd(ll x,ll y) {if(x%y==0) return y;return gcd(y,x%y);}
int main()
{
ll i,j;
T=read();
while(T--)
{
ll ans=0;tp=1;
n=read();
fo(i,1,n) a[i]=read(),ans=max(ans,a[i]);
s[tp]=1,g[tp]=a[1];
fo(i,2,n)  //枚举右端点
{
ll tmp;jtp=0;
s[++tp]=i,g[tp]=a[i];  //push
for(j=tp-1;j;j--) g[j]=gcd(g[j],g[j+1]);  //更新gcd
fo(j,1,tp)
if(g[j]>g[j-1] || j==1)
ss[++jtp]=s[j],gg[jtp]=g[j];
tp=jtp;
fo(j,1,tp)
{
s[j]=ss[j],g[j]=gg[j];
ans=max(ans,g[j]*(i-s[j]+1));
}
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: