题意:给定n和k,找到一个严格递增的序列,使得a1+a2+...+ak=n并且他们的最大公约数最大
思路:令a1 = q*b1 ,a2 = q*b2 ... ak = q*bk 则q(b1+b2+..+bk)=n.所以q为n的约数,又由序列递增且都为正数可知n至少要等于1+2+...+k=(1+k)k/2 不满足条件则不能构成。
然后枚举从大开始枚举n的约数q,只需使序列等于{1,2,3,4......,k-1,n/q-sum} [sum=(1+2+3...+ak-1)] 其中 n/q-sum>k-1。找到q后,所有的数等乘上q就是答案序列
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
//思路: q(a1+..+ak)=n q是n的因数 并且至少要满足 a1+..+ak<=n
//a1+..+ak = n/q ak = n/q - (a1+..ak-1) >0
int main()
{
long long n,k;
//freopen("in.txt","r",stdin);
while(~scanf("%I64d%I64d",&n,&k))
{
vector<int> v;
map<int,int> vis;
if((1+k)>(2*n)/k)//这里是整型可能无法精确比较
{
printf("-1\n");
continue;
}
long long aa=1,d=-1;
long long ak;
long long sk_1 = ((1+k-1)*(k-1))/2;//这个可能会爆 声明为long long
int len=sqrt(n);
for(int q=1;q<=len;q++)
{
if(n%q==0)
{
v.push_back(q);
v.push_back(n/q);
vis[q]=1;
vis[n/q]=1;
}
}
sort(v.begin(),v.end());
for(int i=v.size()-1;i>=0;i--)
{
int q=v[i];
if(vis[q]==0)continue;
vis[q]=0;
aa=n/q - sk_1;
if(aa>k-1)
{
ak=aa;
d=q;
break;
}
}
if(d==-1)
{
printf("-1\n");
continue;
}
for(int i=1;i<=k-1;i++)
printf("%I64d ",d*i);
printf("%I64d\n",d*ak);
}
}
探讨了如何找出一个严格递增的整数序列,该序列之和为n,且序列元素的最大公约数最大。文章提供了一种有效算法,并通过代码实现了解决方案。
439

被折叠的 条评论
为什么被折叠?



