题解:Maximal GCD

Maximal GCD 

https://www.luogu.com.cn/problem/CF803C




 

 -问题描述

请你构造一个长度为 k 的严格上升正整数序列,使得所有数的和恰好为 n,并且所有数的最大公约数最大。输出这个序列。如果没有合法的序列输出 −1。如果有多个合法的序列,可以输出任意一个。

1≤n,k≤1e10

 - 解题思路

题目讲了,这是一个严格递增的正整数序列,那么要使得值最小的情况就是 1,2,3,4...... 而它的总和是 (n×(n+1))/2,题目要我们把能找到这个序列的最大公约数和序列最小情况的总和作比较,若该最小总和更大,则一定不可能构造出一个符合条件的序列,否则则一定可以构造出一组满足条件的序列。

 - 算法描述

#include<bits/stdc++.h>

using namespace std;

using ll = long long;

ll n, k;

// 检查是否可以构造一个和为 n 的 k 个数的序列

bool check(ll n)

{ 

    return k + 1 <= n * 2 / k;

}

int main() {

    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

    cin >> n >> k;

    if (!check(n)) {

        cout << -1<<'\n';

        return 0;

    }

    ll ans = 0; // 初始化 ans 为 0,用于存储最大公约数的候选值

    // 遍历从 1 到 sqrt(n) 的所有整数 i

    for (ll i = 1; i * i <= n; ++i) {

        // 如果 i 是 n 的因数,并且可以构造一个和为 n/i 的 k 个数的序列

        if (n % i == 0 && check(n / i)) {

            // 更新 ans 为 i 和当前 ans 的较大值

            ans = max(ans, i);

        }

        // 如果 i 是 n 的因数,并且可以构造一个和为 i 的 k 个数的序列

        if (n % i == 0 && check(i)) {

            // 更新 ans 为 n/i 和当前 ans 的较大值

            ans = max(ans, n / i);

        }

    }

    // 输出 k-1 个数,每个数都是 ans 的倍数,且递增

    for (int i = 1; i <= k - 1; i++) {

        cout << ans * i << " ";

        // 从 n 中减去已经输出的数的和

        n -= ans * i;

    }

    // 输出最后一个数,使得这 k 个数的和为 n

    cout << n << '\n';

    return 0;

}

 - 力扣提交结果

 - 分析、讨论与总结

从1开始·一直枚举到k−1,用 n 累减每一个数,最后将剩下值输出。这种枚举方式是一定不会有重复的,但要注意每一个数在输出时都要乘以之前求出的最大公因数。同时,本题还需要注意看题目的数据范围,我们知道是要开long long的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值