zoukankan      html  css  js  c++  java
  • Codeforces H. Maximal GCD(贪心)

    题目描述:

    H. Maximal GCD
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    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
    Copy
    6 3
    Output
    Copy
    1 2 3
    Input
    Copy
    8 2
    Output
    Copy
    2 6
    Input
    Copy
    5 3
    Output
    Copy
    -1

    思路:

    这个题是要给一个数n,一个数k,看能不能凑出一组含k个元素的严格递增数列,这组数的和为n,还要让这组数的最大公约数最大。

    刚开始,a1+a2+...+ak=n>=a1+(a1+1)+(a1+2)+...+(ak+k-1),解得1<=a1<=(n-k*(k-1)/2)/k,既然要求公约数最大,把a的所有因数找出来,从大往小一个个试,

    比如,找到一个f是a1的因数,既然要f为这组数的gcd,那f一定也是n的因数,检查一下,不是就跳过,是就n/f,变成找一个严格递增数列和为n/f,就不用考虑公因数了。

    刚开始把过多的注意力放到了a1上,就把所有a1可能值一个个遍历,分别找因数,分别检查,结果是错的,而且程序逻辑及其混乱+复杂,还有好多要特判的地方(疯了我已经快)因为每一个a1都有因数1,最后对于较大的a1来说(从大往小检查)总会到1就停止,以为算出了最终结果。

    所以后来把所有a的所有因数放到一个set里,也方便找最大值,从大往小遍历所有因数。就好了。。。吗?

    结果超时。

    仔细想想,怎么办。既然最后都是a1的因数f如果满足题目条件,那么它也是n的因数,那就把n的因数找出来就好了啊。

    (٩(๑>◡<๑)۶),注意的是在枚举n的因数是不要忘了f要满足a1的上下界的限制,满足的才加到set中去。

    但是但是,还要注意,一开始判断可不可能构造出这么一个数列,a1+a2+...+ak=n>=ka1+k*(k-1)/2>=k+k*(k-1)/2,以为完了?nonono,要注意题目数据范围,如果来个4*10^9这种,long long也存不下啊,那咋办,用double来存k吧...

    Type

    Size

    数值范围

    无值型void

    0 byte

    无值域

    布尔型bool    

    1 byte

    true   false

    有符号短整型short [int] /signed short [int]

    2 byte

    -32768~32767

    无符号短整型unsigned short [int]  

    2 byte

    0~65535

    有符号整型int /signed [int]

    4 byte

    -2147483648~2147483647

    无符号整型unsigned [int]

    4 byte

    0~4294967295

    有符号长整型long [int]/signed long [int]

    4 byte

    -2147483648~2147483647

    无符号长整型unsigned long [int]

    4 byte

    0~4294967295

    long long

    8 byte

    0~18446744073709552000

    有符号字符型char/signed char

    1 byte

    -128~127

    无符号字符型unsigned char

    1 byte

    0~255

    宽字符型wchar_t (unsigned short.)

    2 byte

    0~65535

    单精度浮点型float

    4 byte

    -3.4E-38~3.4E+38

    双精度浮点型double

    8 byte

    1.7E-308~1.7E+308

    long double

    8 byte

     

    (上表来源见下面博客)

    知识点:贪心,数论(一点点)

    代码:

     1 #include <iostream>
     2 #include <cmath>
     3 #include <vector>
     4 #include <set>
     5 #include <algorithm>
     6 using namespace std;
     7 long long n;
     8 double k;
     9 set<long long> fac;
    10 vector<long long> num;
    11 int main()
    12 {
    13     cin >> n >> k;
    14     if(k+k*(k-1)/2<=n)
    15     {
    16         long long uper1 = (n-k*(k-1)/2)/k;
    17         long long lower1 = 1;
    18         //cout << uper1 << " " << lower1 << endl;
    19         long long qz = 1;
    20         /*for(long long a = uper1; a>=lower1; a--)
    21         {
    22             for(long long i = 1; i<sqrt(a)+1; i++)
    23             {
    24                 if(a%i==0)
    25                 {
    26                     fac.insert(i);
    27                     fac.insert(a/i);
    28                 }
    29             }
    30         }*/
    31         for(long long i = 1;i<sqrt(n)+1;i++)
    32         {
    33             if(n%i==0)
    34             {
    35                 if(i<=uper1)
    36                 {
    37                     fac.insert(i);
    38                 }
    39                 if(n/i<=uper1)
    40                 {
    41                     fac.insert(n/i);
    42                 }
    43             }
    44         }
    45         /*cout << "fac " << endl;
    46         for(auto ite = fac.rbegin();ite!=fac.rend();ite++)
    47         {
    48             cout << *ite << " ";
    49         }
    50         cout << endl;*/
    51         for(auto ite = fac.rbegin(); ite!=fac.rend(); ite++)
    52         {
    53             //cout << "ite " << *ite << endl;
    54             int flag = 1;
    55             num.clear();
    56             long long sum = n/(*ite)-1;
    57             int shu = 1;
    58             num.push_back(shu);
    59             if(sum)
    60             {
    61                 shu++;
    62                 while(shu<=sum&&num.size()<k-1)
    63                 {
    64                     num.push_back(shu);
    65                     sum -= shu;
    66                     shu++;
    67 
    68                 }
    69                 if(shu<=sum)
    70                 {
    71                     qz = *ite;
    72                     //cout << "qz " << qz << endl;
    73                     num.push_back(sum);
    74                     break;
    75                 }
    76             }
    77             else
    78             {
    79                 qz = *ite;
    80                 break;
    81             }
    82         }
    83         for(int i = 0;i<num.size();i++)
    84         {
    85             cout << qz*num[i] << " ";
    86         }
    87         cout << endl;
    88     }
    89     else
    90     {
    91         cout << -1 << endl;
    92     }
    93     return 0;
    94 }

    参考资料:

    年少轻狂12138,C++基本数据类型大小及表示范围,https://blog.csdn.net/weixin_40709898/article/details/79368310(间接引用,因为上面的博客也是转载但找不到原博客)

  • 相关阅读:
    HashMap源码分析——基于jdk1.7
    HashMap线程不安全的体现
    Java线程状态转换
    Java多线程——中断机制
    ThreadPoolExecutor解析
    Java中的CAS原理
    AQS框架源码分析-AbstractQueuedSynchronizer
    深入学习CSS外边距margin(重叠效果,margin传递效果,margin:auto实现块级元素水平垂直居中效果)
    CSS布局 两列布局之单列定宽,单列自适应布局思路
    JavaScript 基本类型和引用类型
  • 原文地址:https://www.cnblogs.com/zhanhonhao/p/11248602.html
Copyright © 2011-2022 走看看