1. 程式人生 > >第八屆藍橋杯省賽 分巧克力

第八屆藍橋杯省賽 分巧克力

ret else pac AC 時間復雜度 輸出格式 names std mil

問題描述
  兒童節那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友們。
  小明一共有N塊巧克力,其中第i塊是Hi x Wi的方格組成的長方形。


  為了公平起見,小明需要從這N塊巧克力中切出K塊巧克力分給小朋友們。切出的巧克力需要滿足:

  1. 形狀是正方形,邊長是整數
  2. 大小相同


  例如一塊6x5的巧克力可以切出6塊2x2的巧克力或者2塊3x3的巧克力。


  當然小朋友們都希望得到的巧克力盡可能大,你能幫小Hi計算出最大的邊長是多少麽?
輸入格式
  第一行包含兩個整數N和K。(1 <= N, K <= 100000)
  以下N行每行包含兩個整數Hi和Wi。(1 <= Hi, Wi <= 100000)


  輸入保證每位小朋友至少能獲得一塊1x1的巧克力。
輸出格式
  輸出切出的正方形巧克力最大可能的邊長。
樣例輸入
2 10
6 5
5 6
樣例輸出
2


思路

  順序枚舉所有可能的正方形巧克力的邊長,時間復雜度為$O(n^2)$,會超時。可以用二分進行優化,時間復雜度為$O(nlogn)$


AC代碼

 1 #include <stdio.h>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxn = 100000 + 5;
 5 int w[maxn], h[maxn];
 6 int n, k;
7 8 int solve(int l, int r) { 9 int low = l, high = r; 10 while(low <= high) { 11 int mid = (low + high) / 2; 12 int cnt = 0; 13 for(int i = 0; i < n; i++) { 14 cnt += (w[i] / mid) * (h[i] / mid); 15 if(cnt >= k) break; 16 } 17 if
(cnt >= k) { 18 low = mid + 1; 19 } 20 else { 21 high = mid -1; 22 } 23 } 24 return low - 1; 25 } 26 27 int main() { 28 while(scanf("%d%d", &n, &k) == 2) { 29 int max_len = 0; 30 for(int i = 0; i < n; i++) { 31 scanf("%d%d", &w[i], &h[i]); 32 max_len = max(max_len, min(w[i], h[i])); 33 } 34 printf("%d\n", solve(1, max_len)); 35 } 36 return 0; 37 }

如有不當之處歡迎指出!

第八屆藍橋杯省賽 分巧克力