E - 調合と目標量 / Mixing and Target Amount 解説 by admin
Gemini 3.0 Flash (Thinking)Overview
Given \(N\) chemicals, each with three choices — “don’t use”, “normal mode (\(A_i\) mL)”, or “heated mode (\(B_i\) mL)” — the problem asks whether it is possible to make the total volume exactly \(K\) mL.
Analysis
Since there are 3 choices for each chemical, naively checking all combinations would result in a computational complexity of \(3^N\). Given the constraint \(N \le 26\), we get \(3^{26} \approx 2.5 \times 10^{12}\), making it impossible to complete a brute-force search within the time limit.
On the other hand, if we consider another classic technique, dynamic programming (DP), the target volume \(K\) can be as large as \(10^{15}\), so a DP indexed by the sum is also infeasible.
Therefore, we utilize a technique called “Meet-in-the-middle”. By splitting the \(N\) elements into two halves (\(N/2\) each) and enumerating all combinations separately for each group, the number of combinations per group becomes \(3^{N/2}\). For \(N=26\), we have \(3^{13} = 1,594,323\), which is well within a manageable range.
Algorithm
The procedure for meet-in-the-middle is as follows:
- Split into groups: Divide the \(N\) chemicals into the first \(N/2\) and the remaining ones.
- Enumerate (first half): For the first half of the chemicals, enumerate all possible total volumes and store them in a set (e.g., a Set).
- At this point, totals exceeding \(K\) can be excluded (since all chemical volumes are positive).
- Enumerate (second half): Similarly, enumerate all possible total volumes for the second half of the chemicals.
- Matching: For each total volume \(s_2\) obtained from the second half group, check whether a value \(s_1 = K - s_2\) exists in the set from the first half group.
- If such a value exists, it is possible to achieve a total of \(K\) (
Yes). - If no match is found after checking all \(s_2\), it is impossible (
No).
- If such a value exists, it is possible to achieve a total of \(K\) (
Complexity
- Time complexity: \(O(3^{N/2})\)
- The enumeration for each half takes \(3^{N/2}\), and the matching step takes roughly a constant factor times \(3^{N/2}\). For \(N=26\), \(3^{13} \approx 1.6 \times 10^6\), so it runs fast enough even in Python.
- Space complexity: \(O(3^{N/2})\)
- Memory for storing up to \(3^{N/2}\) elements is needed to hold all possible total volumes from the first half group.
Implementation Tips
Using a set: By storing the first half’s total volumes in a
set, the lookup “does this value exist?” during the second half’s search can be performed in average \(O(1)\) time.Pruning: By discarding combinations as soon as the total exceeds \(K\), we can reduce both memory consumption and computation time.
Efficient enumeration: The implementation goes smoothly by processing chemicals one by one: for the current “set of possible sums,” create a new set by adding \(0, A_i, B_i\) from the new chemical to each existing sum.
Source Code
import sys
def solve():
# Fast input reading from standard input
input_data = sys.stdin.read().split()
if not input_data:
return
# N is the number of drugs, K is the target volume
N = int(input_data[0])
K = int(input_data[1])
A = []
B = []
for i in range(N):
A.append(int(input_data[2 + 2*i]))
B.append(int(input_data[3 + 2*i]))
# Using the meet-in-the-middle technique to reduce complexity from 3^N to 3^(N/2)
# N <= 26, so 3^26 is too large (~2.5 * 10^12), but 3^13 is manageable (~1.6 * 10^6)
mid = N // 2
def get_possible_sums(a_part, b_part, target):
"""
Calculates all possible sums of solution volumes for a given set of drugs.
Each drug can be used in mode A, mode B, or not at all.
"""
ps = {0}
for a, b in zip(a_part, b_part):
# For each drug, there are three choices for its contribution to the sum:
# 1. Not used: The sum remains s (already present in ps).
# 2. Mode A: The sum becomes s + a.
# 3. Mode B: The sum becomes s + b.
# Pruning sums that already exceed the target volume K.
new_a = {s + a for s in ps if s + a <= target}
new_b = {s + b for s in ps if s + b <= target}
# Update the set of possible sums with the new options
ps |= new_a
ps |= new_b
return ps
# Generate all possible sums for the two halves of the drugs
sums1 = get_possible_sums(A[:mid], B[:mid], K)
sums2 = get_possible_sums(A[mid:], B[mid:], K)
# Meet-in-the-middle check:
# We need to find if there exists s1 in sums1 and s2 in sums2 such that s1 + s2 = K.
# This is equivalent to checking if (K - s1) exists in sums2.
# Optimization: Iterate over the smaller set to minimize the number of lookups
if len(sums1) > len(sums2):
sums1, sums2 = sums2, sums1
found = False
for s in sums1:
if (K - s) in sums2:
found = True
break
# Output the result
if found:
print("Yes")
else:
print("No")
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-thinking.
投稿日時:
最終更新: