Official

B - 果樹園の収穫 / Orchard Harvest Editorial by physics0523


まず、各果樹園に着目しましょう。

\(A_i\) 個の果物が実っている果樹園で \(1\) 日 \(B_i\) 個までの収穫を繰り返すと、以下のことが起こります。

  • \(B_i\) 個の収穫を \(\lfloor \frac{A_i}{B_i} \rfloor\) 日行える。 ( \(\lfloor x \rfloor\) は \(x\) の小数点以下切り捨て )
  • 最後に、 \(A_i\) を \(B_i\) で割った余りの個数だけの収穫を \(1\) 日行える。

この収穫を全ての果樹園について集計した上で、個数の多い収穫から順に行っていくのが最善です。

集計は、「 \(x\) 個の収穫を \(y\) 日間」というデータを \(x\) の降順 (大きい方から順) にソートすればよいです。
そして、ソートした収穫を収穫日数の合計が \(K\) に達するか全ての収穫をやり尽くすまで続ければよいです。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;
using ll=long long;
using pl=pair<ll,ll>;

int main(){
  ll N,K;
  cin >> N >> K;
  vector<pl> vp;
  for(ll i=0;i<N;i++){
    ll A,B;
    cin >> A >> B;
    vp.push_back({B,A/B});
    vp.push_back({A%B,1});
  }
  sort(vp.rbegin(),vp.rend());
  
  ll res=0;
  for(auto &nx : vp){
    ll day=min(K,nx.second);
    K-=day;
    res+=nx.first*day;
  }
  cout << res << "\n";
  return 0;
}