zoukankan      html  css  js  c++  java
  • BZOJ-4488:最大公约数(GCD)

    给定一个长度为 N 的正整数序列Ai对于其任意一个连续的子序列
    {Al,Al+1...Ar},我们定义其权值W(L,R )为其长度与序列中所有元素的最大公约数的乘积,即W(L,R) = (R-L+1) ∗ gcd (Al..Ar)。 
    JYY 希望找出权值最大的子序列。

    Input

    输入一行包含一个正整数 N。
    接下来一行,包含 N个正整数,表示序列Ai
    1 < =  Ai < =  10^12, 1 < =  N < =  100,000

    Output

    输出文件包含一行一个正整数,表示权值最大的子序列的权值。

    Sample Input5 30 60 20 20 20

    Sample Output80 //最佳子序列为最后 4 个元素组成的子序列

    题意:求最大的ans=区间长度*区间最大公约数。

    思路:我们考虑到gcd的个数是log级别的,我们对于每个gcd,记录第一个位置即可,开始以为是分治求,这是显然可以的。但事实上没有必要,我们从前向后扫描,当扫描到a[i]时,对于之前的所有gcd,用其第一次出现的位置更新一遍答案,同时把每个gcd和a[i]求gcd,如果第一次出现,则记录其对应位置。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100010;
    map<ll,int>mp,tp;
    map<ll,int>::iterator it;
    int main()
    {
        int N,i; ll x,ans=0;
        scanf("%d",&N);
        for(i=1;i<=N;i++){
            scanf("%lld",&x); ans=max(ans,x);
            for(it=mp.begin();it!=mp.end();it++){
                ll g=__gcd(x,(*it).first);
                ans=max(ans,(ll)(i-(*it).second+1)*g);
                if(tp.find(g)==tp.end()) tp[g]=(*it).second;
            }
            if(tp.find(x)==tp.end()) tp[x]=i;
            mp=tp; tp.clear();
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    常见HTTP状态码
    Spring MVC 原理小结
    RESTful API
    java:IO流学习小结
    理解 Statement 和 PreparedStatement
    Hibernate缓存原理与策略
    APP运营
    网站常见术语
    php常见术语
    运维------术语名词
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9173757.html
Copyright © 2011-2022 走看看