分析
考虑从 \(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; }
来源:https://www.cnblogs.com/hlw1/p/11483499.html