Maximal GCD
题目传送门
题意:给你两个数n,k。要你找一个严格连续递增数列,要求序列有k个元素,和为n并且gcd最大。
思路:很容易知道,要使得gcd最大,那么最大公约数必为数列首项,所以其最大公约数一定是n的因子。最好的情况为1d,2d,3d……,kd(d为最大公约数),即有 k*(k+1)/2 个d。因此,我们只需要求出n的因子,找到小于等于n/k*(k+1)/2中最大的因子就是最优的d,然后按照1d,2d,3d……,xd凑出数列即可。
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#include <functional>
#define inf 10000000
using namespace std;
typedef long long ll;
const int MAXN=5e6+10;
const int MAX=1e6+10;
const double eps=1e-6;
ll n,k;
ll s[MAX];
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
cin>>n>>k;
if((double)(k+1)>(double)(2*n/k)){
cout<<-1<<endl;
return 0;
}
int cnt=1;
for(int i=1;i<=sqrt(n);i++){
if(n%i==0)
s[cnt++]=i,s[cnt++]=n/i;
}
sort(s+1,s+cnt+1);
ll d=2*n/(k*(k+1));
for(int i=cnt-1;i>=1;i--){
if(s[i]<=d){
d=s[i];
break;
}
}
ll sum=0;
for(ll i=1;i<=k;i++){
if(i==k){
printf(" %lld\n",n-sum);
return 0;
}
sum+=i*d;
if(i==1) printf("%lld",i*d);
else printf(" %lld", i*d);
}
return 0;
}