zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    正则表达式
    Java 枚举(enum) 详解7种常见的用法
    【20170921】(Unfinished)2017暑假北京学习 day 2
    (Unfinished)2017暑假北京学习 day 2
    Openjudge NOI题库 数论4975 两只鼹鼠
    Openjudge NOI题库 数论185 反正切函数的应用
    Noip1998 提高组3 卢斯加法表
    【自己的小玩具程序】化学方程式配平【测试中】【未完成】
    Code Vs 1010 过河卒
    NOI 练手题 图像旋转翻转变换
  • 原文地址:https://www.cnblogs.com/kannyi/p/9610761.html
Copyright © 2011-2022 走看看