題目鏈接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=49313
題意:求區間長度*區間gcd的最大值。
題解:由於不同的gcd值很少,可以枚舉右區間,用map記錄gcd值的最左下標,更新ans。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int N=100005;
ll a[N],ans;
int n;
map<ll,int>mp[2];
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
map<ll,int>::iterator it;
void solve(int th,int i) {
mp[th].clear();
for(it=mp[th^1].begin(); it!=mp[th^1].end(); it++) {
ll k=it->first;
ll x=gcd(k,a[i]);
if(mp[th].find(x)==mp[th].end()) {
mp[th][x]=mp[th^1][k];
} else {
mp[th][x]=min(mp[th][x],mp[th^1][k]);
}
ans=max(ans,x*(i-mp[th][x]+1));
}
if(mp[th].find(a[i])==mp[th].end()) {
mp[th][a[i]]=i;
} else {
mp[th][a[i]]=min(mp[th][a[i]],i);
}
ans=max(ans,a[i]*(i-mp[th][a[i]]+1));
}
int main() {
//freopen("test.in","r",stdin);
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
mp[0].clear(),mp[1].clear();
for(int i=1; i<=n; i++)scanf("%lld",&a[i]);
ans=a[1];
mp[0][a[1]]=1;
for(int i=2; i<=n; i++) {
if(i&1)solve(0,i);
else solve(1,i);
}
printf("%lld\n",ans);
}
return 0;
}