zoukankan      html  css  js  c++  java
  • [JSOI 2015]最大公约数

    Description

    题库链接(最近 ( ext{bzoj}) 维护上不去,就给洛谷的链接了...

    给定长度为 (n) 的正整数序列 (A)。定义一连续子段 ([l,r]),其权值为 [left(gcdlimits_{lleq ileq r}^{}A_i ight) imes (r-l+1)]

    求子段最大权值为多少。

    (1leq nleq 100000,1leq A_ileq 10^{12})

    Solution

    显然对于一个确定的右端点,其左端点所有取值中,一整段的 (gcd) 种数是不超过 (log A_i) 的。

    我们只需存下这 (log A_i) 个公约数并记录对应的最靠左的左端点即可。

    时间复杂度为 (O(nlog^2 A_i))

    Code

    #include <bits/stdc++.h>
    #define ll long long
    #define pli pair<ll, int>
    #define fr first
    #define sc second
    #define pb push_back
    using namespace std;
    const int N = 100000+5;
    
    int n, cnt;
    ll a[N], ans;
    vector<pli > g[N];
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a%b) : a; }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
        for (int i = 1; i <= n; i++) {
            cnt = 0;
            for (int j = 0, sz = g[i-1].size(); j < sz; j++) {
                pli x = g[i-1][j];
                ll t = gcd(a[i], x.fr);
                ans = max(ans, t*(i-x.sc+1));
                if (!cnt || t != g[i][cnt-1].fr) g[i].pb(pli(t, x.sc));
                ++cnt;
            }
            pli x = pli(a[i], i);
            ll t = gcd(a[i], x.fr);
            ans = max(ans, t*(i-x.sc+1));
            if (!cnt || t != g[i][cnt-1].fr) g[i].pb(pli(t, x.sc));
        }
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    Git 使用规范流程
    关于Python的super用法研究
    python中try except处理程序异常的三种常用方法
    break 和 continue 语句, 以及循环中的 else 子句
    杂记(python)
    Request和Response
    MVC项目开发步骤
    Web中单元测试步骤
    JSP中的细节
    WEB中地址的写法
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/11575640.html
Copyright © 2011-2022 走看看