首页 > 代码库 > NOIp模拟2 最大公约数

NOIp模拟2 最大公约数

 

试题描述

话说CD比较欠扁,他表示在课室的日子没有教主在旁边打他的日子太寂寞了,所以这一晚,他终于来到了电脑室被打。由于CD是大家的宠物,于是大家都来打CD了。电脑室里有n个人,第i个人希望打CD ai下。但是太多人打CD,他又会不爽,于是他规定只能有K个人打到他,并且为了公平起见,最终K个人打他的次数都必须是相同的,CD规定这个次数就是这K个人希望打他的次数的最大公约数。为什么是最大公约数呢?因为他觉得被打的次数是GCD的话他才会变成Glad CD。之前说了,CD比较欠扁,于是CD希望,K个人打他的次数的和最大。你能告诉他他最后总共会被打多少下么?

输入格式

第一行两个正整数n,k。
第二行n个正整数,表示每个人希望打CD多少下。

输出格式

输出一个正整数表示CD会被打多少下。

输入示例

3 1
1 2 3

输出示例

3

注释说明

对于30%的数据,保证k≤n≤20。
对于50%的数据,保证输入中所有数小于5000。
对于100%的数据,保证输入中所有数小于500000,k≤n≤500000。

 

【分析】

一开始不会做,桶排然后存在数组里强行枚举能搞个90(还不错?)。

其实正解就是桶排啦,不过是枚举GCD后是再统计GCD倍数的个数,这样的话可以在很小很小次数内得到正解(最坏情况大概是所有数互质?不过50w个互质的数应该也不太可能会在数据里)。

 

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, k, t, a[500050], b[500050], c[500050], maxx, tot, sum[500050];
 5 
 6 int main() {
 7     maxx=-0x7fffffff;
 8     cin >> n >> k;
 9     for (int i=1;i<=n;++i) {
10         scanf("%d", &a[i]);
11         maxx=max(maxx, a[i]);
12         b[a[i]]++;
13     }
14     for (int i=maxx;i;--i) {
15         tot=0;
16         for (int j=i;j<=maxx;j+=i)
17             tot+=b[j];
18         if (tot>=k) {
19             cout << k*i << endl;
20             return 0;
21         }
22     }
23 }

 

NOIp模拟2 最大公约数