codeforces 803C - Maximal GCD

探讨了如何找出一个严格递增的整数序列,该序列之和为n,且序列元素的最大公约数最大。文章提供了一种有效算法,并通过代码实现了解决方案。

题意:给定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);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值