UVALive 6582 Magical GCD

題目鏈接: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章