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(间接引用,因为上面的博客也是转载但找不到原博客)

猜你喜欢

转载自www.cnblogs.com/zhanhonhao/p/11248602.html