C - 均等な荷分け / Equal Load Distribution Editorial by admin
Gemini 3.0 FlashOverview
This problem asks: given a row of packages, divide them into groups (carts) without changing their order, such that the total weight of each group is equal, and find the maximum number of groups possible.
Analysis
1. Using Prefix Sums
When dividing packages into consecutive groups, let the total weight of each group be \(w\). Then, the “cumulative weight of packages (prefix sum)” at each group boundary, counted from the left, must take the values \(w, 2w, 3w, \dots, kw\) (where \(kw\) is the total weight \(S\) of all packages).
For example, if the weights are \([1, 2, 1, 1, 1]\) and we decide each group’s weight should be \(w=3\): - The prefix sums are \([1, 3, 4, 5, 6]\). - The prefix sums at the boundaries are \(3, 6\), both of which exist in the prefix sum list.
2. Candidates for Each Group’s Weight \(w\)
To maximize the number of carts \(k\), we need to make each group’s weight \(w\) as small as possible. The possible values of \(w\) are limited to “the total weight when combining the first few packages from the left”. In other words, the \(N\) values contained in the prefix sum list are the candidates for \(w\).
3. Efficient Verification
To check whether a given \(w\) satisfies the conditions, we verify the following two points: 1. The total weight \(S\) is divisible by \(w\) (\(k = S/w\) is an integer). 2. The values \(2w, 3w, \dots, (k-1)w\) all exist in the prefix sum list.
By storing the prefix sum list in a set, we can check whether a specific value exists in \(O(1)\) time.
Algorithm
- Compute the prefix sums of the package weights and store them in a list
prefix_sumand a setp_set. - Let \(S\) be the total weight of all packages.
- Examine each element \(w\) of
prefix_sumin increasing order (from left to right), and perform the following:- If \(S\) is not divisible by \(w\), skip to the next \(w\).
- If \(S\) is divisible by \(w\), let \(k = S/w\).
- For \(j = 2, 3, \dots, k-1\), check whether \(j \times w\) is contained in
p_set. - If all values are contained, then \(k\) is the maximum number of groups, so output it and terminate.
Complexity
- Time Complexity: \(O(N \log N)\)
- Computing the prefix sums and storing them in the set takes \(O(N)\).
- The number of checks in the loop, even in the worst case (e.g., when all package weights are \(1\)), is \(O(N/1 + N/2 + \dots + N/N) = O(N \log N)\) by the harmonic series property, which is sufficiently fast.
- Space Complexity: \(O(N)\)
- The list and set for storing prefix sums use \(O(N)\) memory.
Implementation Notes
Try from the smallest \(w\): Since
prefix_sumis always in ascending order, by trying from the beginning of the list, the first \(w\) that satisfies the conditions gives the largest number of groups \(k\).Fast I/O: Since \(N\) can be as large as \(2 \times 10^5\), using
sys.stdin.read().split()or similar to read all input at once can reduce execution time.Early Termination: By terminating the computation and outputting the result as soon as a valid \(w\) is found, unnecessary exploration is avoided.
Source Code
import sys
# 競技プログラミングにおける標準的な高速入力処理
def solve():
# 全ての入力を一度に読み込み、スペース区切りでリスト化する
input_data = sys.stdin.read().split()
if not input_data:
return
# 荷物の個数 N
n = int(input_data[0])
# 各荷物の重さ Hi
h = list(map(int, input_data[1:]))
# 累積和を計算する
# prefix_sum[i] は左から i+1 番目までの荷物の総重量を表す
prefix_sum = [0] * n
current_sum = 0
for i in range(n):
current_sum += h[i]
prefix_sum[i] = current_sum
# 全荷物の総重量 S
total_sum = prefix_sum[-1]
# 累積和の値を集合(set)に格納し、O(1) での検索を可能にする
p_set = set(prefix_sum)
# 使用できる荷台の個数を最大化するためには、各荷台の重量 w を最小化すればよい
# 各荷台の重量 w は、必ずいずれかの累積和の値(prefix_sum[i])と一致する必要がある
# また、w は総重量 total_sum の約数でなければならない
# 累積和は昇順に並んでいるため、順番に w として試すことで
# 最初に見つかった有効な w が、荷台の個数 k = total_sum / w を最大化する
for w in prefix_sum:
# w が総重量を割り切れる場合のみ、均等な荷分けの可能性がある
if total_sum % w == 0:
k = total_sum // w
# 荷台の個数 k は荷物の個数 n を超えることはできない
if k > n:
continue
# 各荷台の重量が w であるとき、累積和の中に w, 2w, 3w, ..., kw が
# すべて存在すれば、連続する荷物を組み合わせて重量 w のグループを k 個作ることができる
# w と kw (= total_sum) は既に存在することが分かっているため、
# 2w から (k-1)w までが累積和に含まれているかを確認する
is_valid = True
for j in range(2, k):
if (j * w) not in p_set:
is_valid = False
break
# 条件を満たす最小の w が見つかったら、その時の k を出力して終了
if is_valid:
print(k)
return
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-preview.
posted:
last update: