题目链接:https://cn.vjudge.net/problem/49313/origin
题目大意:定义一个魔法GCD,规则是用[l,r]区间内的数的gcd*区间长度,求这个魔法GCD的最大值。
这个题上来竟然wa了一发,我们记录最大公约数及其最左的区间
举个栗子:
30 60 20 20 20
我们从第一个数开始求:
(30,1)
(30,1),(60,2)
(10,1),(20,2),(20,2)
(10,1),(20,2),(20,2),(20,2)
(10,1),(20,2),(20,2),(20,2),(20,2)
括号里的第一个参数代表gcd的值,第二个数代表着同一个gcd值最左边的区间
这样暴力一发就好了
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;
struct node{
LL data;
LL pos;
}xin1[200000],xin2[200000];
LL a[200000];
bool cmp(struct node a,struct node b){
if(a.data==b.data){
return a.pos<b.pos;
}
return a.data<b.data;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int top1=0,top2=0;
LL ans=0;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
ans=max(ans,a[i]);//记得要有这一步,我第一发就wa在这里了
}
xin1[top1].data=a[0];
xin1[top1++].pos=0;
for(int i=1;i<n;i++){
top2=0;
for(int j=0;j<top1;j++){
LL k=__gcd(a[i],xin1[j].data);
xin2[top2].data=k;
xin2[top2++].pos=xin1[j].pos;
}
xin2[top2].data=a[i];
xin2[top2++].pos=i;
sort(xin2,xin2+top2,cmp);
top1=0;
LL last=-1;
for(int j=0;j<top2;j++){
if(j==0){
last=xin2[j].data;
xin1[top1].data=xin2[j].data;
xin1[top1++].pos=xin2[j].pos;
}
else{
if(last==xin2[j].data)
continue;
else{
last=xin2[j].data;
xin1[top1].data=xin2[j].data;
xin1[top1++].pos=xin2[j].pos;
}
}
}
for(int j=0;j<top1;j++){
ans=max(ans,xin1[j].data*(i-xin1[j].pos+1LL));
}
}
cout<<ans<<endl;
}
return 0;
}