CodeForces 803 C Maximal GCD(GCD+思维)

You are given positive integer number n. You should create such strictly increasingsequence of k positive numbers a1, a2, ..., ak, that their sum is equal to n and greatest common divisor is maximal.

Greatest common divisor of sequence is maximum of such numbers that every element of sequence is divisible by them.

If there is no possible sequence then output -1.

Input

The first line consists of two numbers n and k (1 ≤ n, k ≤ 1010).

Output

If the answer exists then output k numbers — resulting sequence. Otherwise output -1. If there are multiple answers, print any of them.

Examples

Input
6 3
Output
1 2 3
Input
8 2
Output
2 6
Input
5 3
Output
-1
题意:

给出正整数n我们要创建k个正数1,  2,...,  k的严格增加序列,它们的和等于n,并使其最大公约数是最大的。

序列的最大公约数是:序列的每个元素都可以被它们整除。

如果没有可能的序列,则输出-1

思路:

(1) 若k个数字的gcd为A,那么n一定可以整除A,所以考虑从n的因子里选出这个A来,先求出k个数字可以表示的最小的数,即 1+2+3+...+k = k(k+1)/2

(2) 设a1 a2 ... ak为解,那么a1+a2+...+ak=n,设gcd(a1,a2...,ak)=A,那么 a1=A*b1 ,a2=A*b2 … ak=A*bk。

(3) 那么gcd(b1,b2,...,bk)=1,且A*(b1+b2+...+bk)=n,所以n%A=0,说明A为n的因数。

ps:n/A = b1+b2+...+bk

(1) 首先因为n≤1010,所以通过 k(k+1)/2 可知:k最大为141420。

(2) 然后处理出所有n的因数,因数从大往小找,找到第一个符合 n/A≥k(k+1)/2 的因数即可。反正b1,b2,…,bk它们的gcd是1,直接令前k-1个数分别是1~k-1,第k项为 (n/A-前k项的总和)

(3) 将最后的答案全部乘A即可!

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
ll A[10005],cnt;
//A[]储存n的因子  cnt为因子个数 
void fact(ll n)
{
    ll i;
    for(i=1,cnt=1;i*i<=n;i++)
    {
        if(n%i==0)
        {
            if(n%i!=i)
            {
                A[++cnt]=i;
                A[++cnt]=n/i;
            }
            else A[++cnt]=i;
        }
    }
}
int main()
{
    //k最大为141420 
    ll n,k,i,j;
    while(scanf("%lld%lld",&n,&k)!=EOF)
    {
        ll fk=k*(k+1)/2;     //k个数所能组成的最小值 
        if(k>141420)
            printf("-1
");
        else if(n<fk)
             printf("-1
");
        else
        {
            fact(n);
            sort(A+1,A+cnt+1);
            ll ksum;
            int flag=0;
            for(i=cnt;i>0;i--)
            {
                ksum=n/A[i];  //k个数的总和  
                if(ksum-fk>=0)
                {
                    flag=1;
                    ll sum=0; //前k-1个数的总和 
                    for(j=1;j<k;j++)
                    {
                        printf("%lld ",j*A[i]);
                        sum+=j;
                    }
                    printf("%lld
",A[i]*(ksum-sum));
                    break;
                }
            }
            if(!flag)printf("-1
");
        }
    } 
    return 0;
}
原文地址:https://www.cnblogs.com/kannyi/p/9610761.html