D - 肥料の配分 / Distribution of Fertilizer 解説 by admin
gemini-3.5-flash-thinkingOverview
This problem asks us to determine how to distribute a total of \(K\) bags of fertilizer to maximize the product of the growth values of fruit trees.
We utilize the property that “to maximize the overall product, it is optimal to prioritize raising the lowest growth values, bringing all values as close to equal as possible” (an intuitive property of the AM-GM inequality). Since \(K\) can be very large, we use binary search to efficiently find the final lower bound of the growth values.
Analysis
1. Optimal Strategy for Maximizing the Product
When the sum of two variables \(x, y\) is constant (\(x + y = S\)), their product \(xy\) is larger when the difference between \(x\) and \(y\) is smaller (i.e., when they are as close to equal as possible). This property holds even when there are \(N\) variables. Therefore, the optimal strategy for distributing fertilizer is a greedy approach: “Give fertilizer to the tree with the currently lowest growth value to raise the overall minimum.”
2. Limitations of Simple Simulation
Repeating the operation “give one bag of fertilizer to the tree with the lowest growth value” \(K\) times would yield the optimal solution, but looking at the constraints, \(K \le 10^{18}\). Simulating one bag at a time would exceed the time limit (TLE).
3. Speeding Up with Binary Search
Instead, we consider the decision problem: “Is it possible to make all fruit trees have a growth value of at least \(X\)?”
The total amount of fertilizer needed to raise all trees with growth value less than \(X\) to exactly \(X\) is: $\( \sum_{A_i < X} (X - A_i) \)\( If this required total is at most \)K\(, then it is possible to make all trees have a growth value of at least \)X$.
Since this required amount increases monotonically with respect to \(X\), we can use binary search to efficiently find “the maximum \(X\) such that all trees can have a growth value of at least \(X\).”
Algorithm
Sorting and Prefix Sum Preparation Sort the initial growth values \(A\) of the fruit trees in ascending order. Also, create a prefix sum array
prefto efficiently compute the sum of elements less than a given value \(X\).Determining the Lower Bound \(X\) via Binary Search Implement a function
check(X)that determines “whether all fruit trees can have a growth value of at least \(X\).”- Use binary search (
bisect_left) to find the numberidxof trees with \(A_i < X\). - The amount of fertilizer needed to raise all those trees to \(X\) is computed as
idx * X - pref[idx]. - Return
Trueif this is at most \(K\), otherwise returnFalse.
- Use binary search (
Using this decision function, find the maximum achievable \(X\) via binary search.
- Distributing Remaining Fertilizer and Computing the Final Product
After raising all trees to at least \(X\), there may still be
rem = K - (required fertilizer)bags remaining. These remainingrembags are distributed one by one to trees that have growth value \(X\), raising their growth value to \(X+1\).
The final growth values of the trees are as follows:
- Among the trees that were originally at most \(X\) (\(C\) trees in total), rem of them become \(X+1\), and the remaining \(C - rem\) trees stay at \(X\).
- Trees that originally had a growth value greater than \(X\) remain unchanged at their initial values.
Compute the product of all these values modulo \(10^9 + 7\) cumulatively and output the result.
Complexity
Time Complexity: \(O(N \log N + \log N \log(\max A_i + K))\)
- Sorting the initial array takes \(O(N \log N)\).
- The number of binary search iterations is \(O(\log(\max A_i + K))\), and each iteration performs a
bisect_lefttaking \(O(\log N)\). - The final product computation is \(O(N + \log K)\).
- Overall, this comfortably fits within the time limit.
Space Complexity: \(O(N)\)
- \(O(N)\) memory is used to store the sorted array \(A\) and the prefix sum array
pref.
- \(O(N)\) memory is used to store the sorted array \(A\) and the prefix sum array
Implementation Notes
Judgment Using True Values: The maximization judgment must be performed using true values before taking the modulo \(10^9+7\). Therefore, during the binary search, calculations are done without taking the remainder by
MOD.Distinguishing Between
bisect_leftandbisect_right:bisect_left(A, X): Used to find the number of elements less than \(X\) (the number of trees that need to be raised).bisect_right(A, X): Used to find the number of elements at most \(X\) (the total number \(C\) of trees whose growth value becomes \(X\) after raising).Source Code
import sys
from bisect import bisect_left, bisect_right
def solve():
input = sys.stdin.read
data = input().split()
if not data:
return
N = int(data[0])
K = int(data[1])
A = [int(x) for x in data[2:]]
A.sort()
pref = [0] * (N + 1)
for i in range(N):
pref[i+1] = pref[i] + A[i]
def check(X):
idx = bisect_left(A, X)
cost = idx * X - pref[idx]
return cost <= K
ok = 1
ng = 10**9 + K + 1
while ng - ok > 1:
mid = (ok + ng) // 2
if check(mid):
ok = mid
else:
ng = mid
X = ok
idx = bisect_left(A, X)
cost = idx * X - pref[idx]
rem = K - cost
C = bisect_right(A, X)
MOD = 10**9 + 7
ans = pow(X + 1, rem, MOD) * pow(X, C - rem, MOD) % MOD
for i in range(C, N):
ans = ans * A[i] % MOD
print(ans)
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3.5-flash-thinking.
投稿日時:
最終更新: