1. 程式人生 > >NOIp模擬2 最大公約數

NOIp模擬2 最大公約數

log enter 得到 turn int 寵物 數組 公約數 最終

試題描述

話說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 最大公約數