洛谷P1414 又是毕业季II

洛谷P1414 又是毕业季II

题目背景

“叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻。毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌。1000多个日夜的欢笑和泪水,全凝聚在毕业晚会上,相信,这一定是一生最难忘的时刻!

题目描述

彩排了一次,老师不太满意。当然啦,取每位同学的号数来找最大公约数显然不太合理。于是老师给每位同学评了一个能力值。于是现在问题变为,从n个学生中挑出k个人使得他们的默契程度(即能力值的最大公约数)最大。但因为节目太多了,而且每个节目需要的人数又不知道。老师想要知道所有情况下能达到的最大默契程度是多少。这下子更麻烦了,还是交给你吧~

PS:一个数的最大公约数即本身。

输入格式

第一行一个正整数n。

第二行为n个空格隔开的正整数,表示每个学生的能力值。

输出格式

总共n行,第i行为k=i情况下的最大默契程度。

输入输出样例

输入 #1

1
2
4
1 2 3 4

输出 #1

1
2
3
4
4
2
1
1

说明/提示

【题目来源】

lzn原创

【数据范围】

记输入数据中能力值的最大值为inf。

对于20%的数据,n<=5,inf<=1000

对于另30%的数据,n<=100,inf<=10

对于100%的数据,n<=10000,inf<=1e6


分析

数论题,但是很考验逻辑思维能力,刚开始看题解都没看明白,想了半天就是脑子转不过来,纸上模拟了几次后有点一知半解的感觉了,趁热赶紧记下来。

首先对每个数分析,找出它的所有因子,用一个数组几下因子出现的次数。通过对这些数处理完后我们的数组里的值cnt[i]就代表因子i出现的次数。

然后就可以输出结果了,这也是最神奇的地方。有一点必须想明白,当l小于k时,l个数的最大公因数一定大于k个数的最大公因数,所以用一个for(int i = 1; i <= N; i++),再用一个now = MAX,这里的i表示取i个数,MAX表示输入的几个数中最大的数。

当i等于1时,即取一个数时,最大公因数肯定是所有数的最大值。i继续递增,类似的,此时表示取i个数,所以此时的最大公因数只会比上一个小,所以找最大公因数时只要令now不断递减,即now--

那么什么时候需要递减呢?可以这么想,我取i个数,如果此时的now的出现次数,即cnt[i]比i还要小,也就是说要想当前的now是最大公因子,那么我取i个数每个数都要有这个因子,所以now的出现次数不会比i小,如果小了,那么当前now就不行,只能减1再取判断,直到符合条件,那么此时now一定就是最大公因数。

真是越来越觉得自己菜的不行了,这么简单的逻辑我脑子就是转了半天还是转不过来,心态真有点绷不住了😅😅。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

int cnt[1000010];

int main(int argc, const char *argv[])
{
int N, MAX = -1;
cin >> N;
for(int i = 0; i < N; i++)
{
int temp;
cin >> temp;
if(temp > MAX)
MAX = temp;
int sqr = sqrt(temp);
for(int j = 1; j <= sqr; j++)
{
if(temp % j == 0)
{
cnt[j]++;
if(j * j != temp)
cnt[temp / j]++;
}
}
}
int now = MAX;
for(int i = 1; i <= N; i++)
{
while(cnt[now] < i)
now--;
cout << now << endl;
}

return 0;
}
作者

Jhuoer Yen

发布于

2021-05-28

更新于

2023-09-18

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×