CF803C Maximal GCD

泄露秘密 提交于 2020-01-09 07:08:34

洛谷

CF

分析

考虑从 \(k\) 个数的 \(gcd\) 入手。

设他们的 \(gcd\)\(d\) 。则有 \(d|n\) ,那么这 \(k\) 个数都除以 \(d\) 剩下的和即为 \(\frac{n}{d}\) ,又由于 \(k\) 个数严格上升,那么我们将 \(1\)\(k\) 的和记为 \(sum\) ,有 \(sum=k*(k+1)/2\) 。于是必有 \(sum<=n/d\) ,所以我们可以枚举 \(n\) 的因数,判断是否满足条件,再取最大值即可。

剩下的我们只需构造 \(k\) 个数,使其和等于 \(n/d\) ,最后输出时将每个数再乘 \(d\)

贪心的想,我们直接将这组数构造成 \(1,2,3...k-1,k\) ,若 \(sum<n/d\) ,直接将这组数的最后一个数 \(k\) 更改为 \(k+n/d-sum\) 即可。

一些废话:

这题真的毒瘤。。。。。。本来没想多久就做出来的,结果一改就改了一个上午,总是在第21个点T,把数据蒯下来自己测也确实很慢,但却不知道是为什么,\(O(\sqrt{n})\) 的算法也能这么慢......

下午看了题解,发现和我的方法一模一样,只是代码不同。我这该怎么改啊?

百思不得其解后,发现题解的 \(sum\) ,都是直接写的 \(k*(k+1)/2\) 而不是定义一个变量代替这个式子,于是我用了#define sum (k*(k+1)>>1),,,,,,然后就AC了.......

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define re register
#define sum (k*(k+1)>>1)
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x) {
    T f = 1; x = 0; char c;
    for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    x *= f;
}

ll n, k, mx = 1;

void print(ll d) {
    re ll c = n / d - sum;
    for (re ll i = 1; i <= k; ++i) {
        if (i == k) printf("%lld", (ll)(i + c) * d);
        else printf("%lld ", (ll)i * d);
    }
}

int main() {
    read(n), read(k);
    if (k == 1) {printf("%lld", n); return 0;}
    if (k >= n) {puts("-1"); return 0;}
    if (k >= 1e8) {puts("-1"); return 0;}
    if (sum > n) {puts("-1"); return 0;}
    for (re ll i = 1; i * i <= n; ++i) {
        if (n % i != 0) continue;
        if (i >= sum) mx = max(mx, n / i);
        if (n / i >= sum) mx = max(mx, i);
    }
    print(mx);
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!