CF803C Maximal GCD
分析
考虑从 \(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;
}

浙公网安备 33010602011771号