题意翻译
请你构造一个长度为 kk 的严格上升正整数序列,使得所有数的和恰好为 nn,并且所有数的最大公约数最大。输出这个序列。如果没有合法的序列输出 -1−1。如果有多个合法的序列,可以输出任意一个。
1\le n,k\le 10^{10}1≤n,k≤1010
本题思路
留意序列的最大公约数必定是n的一个因子,假设为d
所以题目可以转化为:寻找一个最大的因子d,使得
1d + 2d + 3d + ... + (k - 1)d <= n (如果不是等于而是小于的时候,我们把剩余的数全部堆到序列最后一项即可)
所以关键是求出n的所有因子,然后从大到小搜索,找到第一个满足条件的d之后构造答案即可
算法步骤
1 输入n, k
2 计算 m = k * (1 + k) / 2
3 求出n的所有因子并从大到小排序保存到数组fac中
4 For d: fac
5 if n / d >= m:
6 ans=[1d, 2d, 3d, ... kd]
7 ans[last] = n - sum(ans[1..k-1]) // 把剩余的数全部放到ans最后一项
8 输出ans
(以上算法未包含答案为-1的情况,请自行补充)
代码:
#include <bits/stdc++.h>
#define ll long long
namespace std;
signed main()
{
ll n,k,m;
cin>>n>>k;
m=k*(k+1)/2;
if(m>n)
{
cout<<"-1";
return 0;
}
int str=0;
for(ll i=1;i*i<=n;i++)
{
if(n%i==0)
{
if(m<=i)
{
str=max(str,n/i);
}
if(m<=n/i)
{
str=max(str,i);
}}}
n/=str;
for(ll i=1;i<k;i++)
{
cout<<i*str<<" ";
n-=i;
}
cout<<n;
return 0;
}
这道题问题所在于有很多样例,所以有些样例的数字很大,一般的int,不能很好的表示,需要用到long long,如何提高数据的存储效率跟运行速度也是编程关键所在。