[BZOJ4488][JSOI2015]最大公约数 DP+STL

一个数的约数大概是log级的,那么右端点确定的若干区间的gcd最多也只有log种。显然,右端点确定时,随着左端点递增,gcd是不降的。
从左往右DP,对于每种以当前点为右端点的区间gcd的取值,记录左端点最左可以延伸到哪。用map搞个映射就好了。复杂度O(nlog^2n)
代码:

#include
#include
#include
#include
#define ll long long
#define chkmax(a,b) a=max(a,b)
#define chkmin(a,b) a=min(a,b)
using namespace std;
typedef mapint> mpli;
int n;
ll a[100010],ans;
mpli mp,tmp;
mpli::iterator it;
ll gcd(ll a,ll b)
{
    if(aif(!b) return a;
    else return gcd(b,a%b);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
    {
        chkmax(ans,a[i]);
        for(it=mp.begin();it!=mp.end();it++)
        {
            ll g=gcd(a[i],it->first);
            chkmax(ans,g*(i-it->second+1));
            if(tmp.count(g)==0) tmp[g]=it->second;
            else chkmin(tmp[g],it->second);
        }
        if(tmp.count(a[i])==0) tmp[a[i]]=i;
        mp=tmp;
        tmp.clear();
    }
    printf("%lld",ans);
    return 0;
}


你可能感兴趣的:(dp,数论,STL)