【JZOJ3780】【UVA1642】Magical GCD

我们两清 提交于 2020-03-15 06:17:06

题目大意:

给一个长度为 \(n\) 的数列,找到一个连续子序列使得子序列的公约数与长度的乘积最大,求这个最大值。

正文:

直接枚举 GCD 区间的右端点 \(r\),再枚举左端点 \(l(l<r)\) 计算 GCD,记录答案。

\(\texttt{50}\) 分。

可以通过上一个枚举的右端点 \((r-1)\) 计算过的 GCD 区间更新当前区间就可以了,这些操作可以通过链表实现。

代码:

for (scanf ("%d", &t); t--; )
{
    memset (a, 0, sizeof(a));
    memset (b, 0, sizeof(b));
    memset (last_, 0, sizeof(last_));
    memset (next_, 0, sizeof(next_));
    ans = 0;
    scanf ("%lld", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf ("%lld", &a[i]);
        b[i] = a[i];
        last_[i] = i - 1, next_[i] = i + 1;
    }
    for (int r = 1; r <= n; r++)
    {
        for (int l = 1; l <= r; l = next_[l])
        {
            b[l] = gcd(b[l], a[r]);
            ans = max(ans, (r - l + 1) * b[l]);
            if(b[l] == b[last_[l]])
            {
                next_[last_[l]] = next_[l];
                last_[next_[l]] = last_[l];
            }
        }
    }
    printf("%lld\n", ans);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!