B - 畑の収穫 / Harvest from the Field 解説 by admin
Claude 4.6 Opus (Thinking)概要
\(M\) 人の作業員を毎日各畑に最適に割り当てて、すべての畑を収穫可能にする最小日数を求める問題。答えは \(\lceil \sum D_i / M \rceil\)(全作業量を1日あたりの総作業力で割った切り上げ)。
考察
重要な気づき:1日あたりの作業力はちょうど \(M\)
毎日 \(M\) 人全員を必ずどこかの畑に割り当てるため、1日あたりの総作業量はちょうど \(M\) です。\(T\) 日間では、総作業量は \(T \times M\) となります。
下界の特定
すべての畑を収穫するのに必要な総作業量は \(\sum_{i=1}^{N} D_i\) です。1日に \(M\) ずつしか進まないので、最低でも次の日数が必要です:
\[T \geq \left\lceil \frac{\sum D_i}{M} \right\rceil\]
この下界は常に達成可能か?
もう一つ考えるべき制約は「1つの畑は1日に最大 \(M\) しか進まない」ため、最も重い畑には \(\lceil D_{\max} / M \rceil\) 日必要です。しかし:
\[\lceil D_{\max} / M \rceil \leq \lceil \sum D_i / M \rceil\]
が常に成立するため(\(D_{\max} \leq \sum D_i\))、結局 \(\lceil \sum D_i / M \rceil\) だけが答えを決定します。
具体例で確認
- \(D = [5, 1]\), \(M = 100\): 合計 \(= 6\), 答え \(= \lceil 6/100 \rceil = 1\) 日。1日目に畑1に5人、畑2に1人、残り94人はどこかに配置(余剰作業は影響なし)。
- \(D = [3, 3, 3]\), \(M = 2\): 合計 \(= 9\), 答え \(= \lceil 9/2 \rceil = 5\) 日。例えば毎日2人ずつ割り振りを工夫すれば5日で全畑の作業量を満たせる。
なぜ下界が達成可能なのか
\(T\) 日間で各畑に必要な作業量を割り振る問題は、以下の条件が満たされれば必ず実行可能です:
- 各畑 \(i\) は1日最大 \(M\) 作業を受けられる → \(D_i \leq T \times M\)(\(T = \lceil \sum D_i / M \rceil\) で保証)
- 全畑の需要の合計が総容量以下 → \(\sum D_i \leq T \times M\)(定義より成立)
よって、\(M\) 人を毎日自由に配分できるため、この下界は常に達成できます。
アルゴリズム
- \(D_1, D_2, \ldots, D_N\) の総和 \(S = \sum_{i=1}^{N} D_i\) を計算する
- 答えは \(\lceil S / M \rceil = \lfloor (S + M - 1) / M \rfloor\) を出力する
計算量
- 時間計算量: \(O(N)\)(配列の総和を計算するだけ)
- 空間計算量: \(O(N)\)(入力配列の格納)
実装のポイント
\(D_i\) と \(M\) が最大 \(10^9\)、\(N\) が最大 \(10^6\) のため、総和は最大 \(10^{15}\) 程度になる。Python では整数オーバーフローの心配はないが、C++ などでは
long longが必要。切り上げ除算は
(S + M - 1) // Mで正しく計算できる。ソートや二分探索は不要で、単純な合計計算のみで解ける。
ソースコード
import math
def solve():
N, M = map(int, input().split())
D = list(map(int, input().split()))
D.sort(reverse=True)
# Binary search on the number of days
lo, hi = 1, max(D)
def check(days):
# With `days` days and M workers per day, total work capacity = days * M
# Each field i needs D[i] work, but also each field needs at least 1 day
# (you can do at most D[i] work per day on field i... no, actually you can
# assign all M workers to one field in one day)
#
# The constraint is: each day, exactly M workers are distributed among fields.
# A field i needs D[i] total work. In `days` days, each field can get at most
# `days * M` work (if all workers go there every day), but the real constraint
# is that the sum of workers assigned each day = M.
#
# Key insight: field i needs at least ceil(D[i] / M) days if we could assign
# all M workers to it. But we need all fields done simultaneously.
#
# Actually, the constraint is:
# 1) days >= ceil(D_max / M) -- we can't finish the hardest field faster
# Wait no, we can assign fewer than M workers per day to a field.
# The hardest field needs D_max work. Even if we assign all M workers
# every day, it takes ceil(D_max / M) days.
# But we also need to handle other fields.
#
# With `days` days, total capacity = days * M.
# We need sum(D) <= days * M (necessary condition).
# Also, each field needs D[i] work done over `days` days where each day
# it can receive between 0 and M workers.
# So each field needs at most M work per day, meaning D[i] <= days * M
# for each field (but since days >= 1 and we binary search, this should hold).
#
# Actually the only constraint is:
# - Total work needed: sum(D) <= days * M
# - No single field requires more than days * M (i.e., D_max <= days * M)
# but since M >= 1, if days >= D_max this holds.
#
# Wait, but each field needs D[i] work. We have days days. Each day we
# distribute M workers. The question is whether we can distribute M workers
# across N fields over `days` days such that field i gets at least D[i] total.
#
# This is feasible if and only if:
# 1) sum(D) <= days * M (enough total capacity)
# 2) max(D) <= days * M (no single field needs more than total possible)
# But condition 2 is implied by condition 1 when N >= 1... no it's not.
# If N=1, both are the same. If N>1, condition 1 is stricter than condition 2
# only if sum > max, which is true when N>1 and all D>0.
#
# Hmm wait. Actually each day each field can get at most M workers.
# So field i can get at most days * M over all days. But also, field i
# can get at most M per day. The real constraint per field is D[i] <= days * M.
# And the global constraint is sum(D[i]) <= days * M.
#
# Since we can freely distribute M workers each day, as long as
# sum(D) <= days * M, we can achieve it. And D_max <= days * M is needed too,
# but for N >= 1, if sum(D) <= days * M then D_max <= sum(D) <= days * M.
#
# So the answer is simply ceil(sum(D) / M).
# But wait... what about D_max? If D_max > sum/N... no.
# ceil(sum(D)/M) >= ceil(D_max/M) only if sum >= D_max, which is always true.
# So the answer is ceil(sum(D) / M).
total = sum(D)
return days * M >= total
# Actually, we also need days >= ceil(D_max / M)... no wait.
# If D_max = 10^9, M = 1, N = 1, answer = 10^9 = ceil(10^9 / 1). Correct.
# The answer is simply ceil(sum(D) / M).
total = sum(D)
ans = (total + M - 1) // M
# But also need ans >= ceil(D_max / M) ... which is always <= ceil(sum/M).
# Hmm, actually not. Consider D = [5, 1], M = 100. sum = 6, ceil(6/100)=1.
# In 1 day, assign 5 to field 1, 1 to field 2, 94 wasted. Works! Answer = 1.
print(ans)
solve()
この解説は claude4.6opus-thinking によって生成されました。
投稿日時:
最終更新: