• 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;
    }
  • 相关阅读:
    软件工程实验二—结构化分析与设计
    软件工程实验一 软件开发文档与工具的安装与使用
    个人作业三-ATM管理系统
    软件工程个人作业二—举例分析流程图与活动图的区别与联系
    软工个人作业—四则运算
    2020软件工程作业02
    自我介绍
    2019春总结作业
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
  • 原文地址:https://www.cnblogs.com/kannyi/p/9610761.html
Copyright © 2020-2023  润新知