[Uva1642]魔法Gcd(数论)

Description

给定n个数,某个连续区间[L,R]的收益为\(gcd(A_l,A_{l+1},A_{l+2}...A_r)*(r-l+1)\)

求收益最大的区间的收益值

\(1 \leq n \leq 50000,A_i<=10^9\)

Solution

设f[i][j]为区间[i,j]的gcd,那么就有\(f[i][j]=gcd(f[i][j-1],A_i)\)

由此可以固定右端点算出每个区间的gcd,同时更新Ans

用一个数组储存当前所有gcd的值,

如果有相同的gcd,与上一个区间合并即可,否则增加一个新的gcd的值

Code

#include <cstdio>
#include <algorithm>
#define N 500010
using namespace std;

int n, A[N], tot, l[N];
long long Ans;

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-')f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}

int gcd(int a, int b) {
    return (b == 0) ? a : gcd(b, a % b);
}

int main() {
    n = read();
    for (int k, i = 1; i <= n; ++i) {
        A[++tot] = read();
        l[tot] = 1, k = 0;
        for (int j = 1; j <= tot; ++j) {
            A[j] = gcd(A[j], A[tot]);
            if (A[j] == A[k]) l[k] += l[j];
            else A[++k] = A[j], l[k] = l[j];
        }
        int s = 0; tot = k;
        for (int j = tot; j; --j) {
            s += l[j];
            Ans = max(Ans, 1ll * A[j] * s);
        }
    }
    printf("%lld\n", Ans);
    return 0;
}

转载于:https://www.cnblogs.com/void-f/p/7735082.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值