AT4842 [ABC136E] Max GCD

原题链接

  • 题解:解决了历史遗留问题。很显然的是,这样操作总和不会变,然后所有 gcd 的可能的取值都是会是 sum 的因子,所以可以 O(sum) 的时间复杂度来枚举 gcd,然后 O(n) 遍历用最小操作来看是否是小于 k,最后取最大。
  • 代码:
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 9, mod = 1e9 + 7;

ll a[N];
ll b[N];
ll sum = 0;
ll n, k;
ll ans;
void check(ll p) {
    ll ssum = 0;
    for (ll i = 1; i <= n; i++) {
        b[i] = a[i] % p;
    }
    sort(b + 1, b + 1 + n);
    ll sub = 0;
    ll add = 0;
    int l = 1, r = n;
    while (l <= r) {
        while (l <= r && b[l] == 0) {
            l++;
        }
        while (l <= r && b[r] == p) {
            r--;
        }
        if (r == l) {
            ssum += min(b[l], p - b[l]);
            break;
        }
        if (l > r) break;
        ssum += b[l];
        ll t = b[l];
        
        b[l] = 0;
        while (l <= r && t > 0) {
            if ( b[r] + t >= p ) {
                t -= (p - b[r]);
                b[r] = p;
                r--;
            } else {
                b[r] += t;
                t = 0;
                break;
            }
        }
    }
    if (ssum <= k) {
        ans = max(ans, p);
    }
}
signed main() {
    cin >> n >> k;
    for (ll i = 1; i <= n; i++) {
        cin >> a[i];
        sum += a[i];
    }
    ans = -1;
    check(sum);
    for (ll i = 1; i * i <= sum; i++) {
        if (sum % i == 0) {
            check(i);
            check(sum / i);
        }
    }
    cout << ans << endl;
    return 0;
}
posted @   u_yan  阅读(58)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
点击右上角即可分享
微信分享提示