CodeForces 803C

来源:互联网 发布:lol网络关注 编辑:程序博客网 时间:2024/06/05 19:06

Maximal GCD

Describtion:

You are given positive integer number n. You should create such strictly increasing sequence 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个严格单调递增的数之和。其中求出k个数的最大公约数最大的情况,有多个的话给出任意一个就可以。

解题思路:
1.既然是要求k个数的最大公约数最大,那么就从最大公约数入手,假设最大公约数是g
2.由于g是每个数的因子,因此可以有:   n = b1*g + b2*g + b3*g + … … + bk*g , 显然这个g也是n的因子
3.根据上式,也就有 n = g*(b1+b2+b3+ …+ bk)。bi也是严格递增的,最多有k个,那么对于g来说是有有下限的,也就是 n/g < (1+k)*k/2
4.枚举数n的全部因子,只要去找前  n 个数即可。不过这样计算的时候,每次需要考虑两个,并取两个因子中更大的可行解。
5.对于同一个g来说,任意的满足的b1,b2,b3,….,bk序列一定可以等价为一个1,2,3,…,i,i+1,..,k-1,bk+x序列(比如 26=2*(1+3+4+5) 等价于 26=2*(1+2+3+7))因为只要将前面少掉的因子全都加到最后一项上,肯定是满足严格单调递增的。
6.由于n也是小于1010,下面如果k>2311=(2.14109)那么k*(k+1)/2是肯定超过n了,根据3可知这是不可能的。以此来防止超过long long的表示范围。(2631=9.231018 ,而k最大也可以取到1010,那么need的计算会超过表示范围)

源代码:

#include<stdio.h>#include<math.h> long long MAX = (1<<31)-1;int main(){    long long n,k;    scanf("%lld %lld",&n,&k);    long long need = k * (k + 1) / 2;    if(n < need || k > MAX)                //防止超过long long的表示范围        puts("-1");    else{        long long g = 1;        long long i = sqrt(n);        for(i; i >=1 ; i--){            if(n % i == 0){                long long now = n / i;                if(now >= need)            //now是个数和,i是因子                     g = g>i?g:i;                if(i >= need)              //考虑i是个数和,need是因子的情况                     g = g>now?g:now;             }        }        long long now = n / g;        for(long long i = 1; i < k; i++){           printf("%lld ",i * g);           now -= i;        }         printf("%lld\n",g * now);    }    return 0;}