UVA-1642 Magical GCD (GCD性质)

题意:一个长度为n的数列,选一个连续子序列,使得子序列的公约数*长度最大,求这个最大值,n<=1e5。

思路:对于一个数字A,其最多不同的gcd值最多只有logA种

每次向右取一个值时,只要和上一个位置的不同gcd值再取gcd就可得到当前位置的不同gcd值

类似的用到这个性质的有HDU-5869,2016icpc大连网络赛


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
map<ll,ll> mp;
ll n,x,ans;

ll gcd(ll x, ll y){
    return y==0?x:gcd(y,x%y);
}

int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        mp.clear();
        ans=0;
        for (int i=1; i<=n; i++){//枚举右端点
            scanf("%lld",&x);
            if (!mp.count(x)) mp[x]=i;
            for (map<ll,ll>::iterator it=mp.begin(); it!=mp.end(); ){
                ll tmp=gcd(x,it->first);
                ans=max(ans,tmp*(i-it->second+1));
                if (!mp.count(tmp))
                    mp[tmp]=it->second;
                else 
                    mp[tmp]=min(mp[tmp],it->second);
                //tmp不可能大于it->first,只可能tmp<=it->first
                if (tmp<it->first)
                    mp.erase(it++);
                else it++;
            }
        }
        printf("%lld\n",ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/leave8426/article/details/80026659
gcd