CF 102697136 - Math Team
The input describes a student's performance across several independent problem sets. Each line has the form a/b, where a is the number of questions answered correctly and b is the total number of questions in that set.
Rating: -
Tags: -
Solve time: 48s
Verified: yes
Solution
Problem Understanding
The input describes a student's performance across several independent problem sets. Each line has the form a/b, where a is the number of questions answered correctly and b is the total number of questions in that set. The task is to combine all sets and print the student's total number of correct answers followed by the total number of incorrect answers, using the same correct/total style.
For example, if the sets are 2/5 and 3/5, the student answered 2 + 3 = 5 questions correctly. There were 5 + 5 = 10 questions in total, so the final result is 5/10. Equivalently, the number of wrong answers is (5 - 2) + (5 - 3) = 5.
The official statement gives a 1 second time limit and 256 MB of memory. It does not publish a numerical upper bound for n on the visible problem page, so the safest design is a single pass through the input with constant extra state. An algorithm with quadratic work would become unsuitable as the number of problem sets grows, while the required computation itself only needs each input line to be processed once.
There are a few small cases where careless parsing or accounting can produce an incorrect result. With a single set such as
1
3/7
the answer is 3/7. A solution that only computes the number of wrong answers but forgets to preserve the number of correct answers would lose information.
A set can also contain zero correct answers. For
1
0/6
the correct output is 0/6. An implementation that treats zero as a missing value, or assumes every set contains at least one correct answer, can fail here.
All questions can be answered correctly as well. For
1
6/6
the output is 6/6, not 6/0. The denominator in the output is the total number of questions, not the number of incorrect questions, despite the wording that asks for the total correct and total wrong counts conceptually. The actual required output format is a slash-separated correct count and total question count.
Finally, the slash is part of the input syntax, not a mathematical division operation. For
2
2/5
4/6
the answer is 6/11. Parsing the two integers around / and adding them separately avoids accidentally performing integer division.
Approaches
A deliberately naive solution could store every problem set seen so far and, after reading each new set, scan the entire stored collection again to recompute the two totals. This is correct because every recomputation considers every set and adds its correct and total counts. After reading k sets, however, it performs k additions, so across n sets the number of set inspections is
[ 1 + 2 + \cdots + n = \frac{n(n+1)}2. ]
For n = 100000, that is 5,000,050,000 set inspections, far beyond what a 1 second program should attempt.
The brute-force method works because the desired result is simply the sum of independent contributions from every set, but it repeatedly processes information that has already been incorporated into the answer. The key observation is that addition is associative. Once the current totals are known, a newly read set only needs to contribute its own correct count and its own total count. There is no reason to revisit earlier sets.
We can consequently maintain two running values. One stores the sum of correct answers, and the other stores the sum of all questions. For every input line a/b, we add a to the first value and b to the second. At the end, those two accumulated values are exactly the required output.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O(n²) | O(n) | Too slow for large n |
| Optimal | O(n) | O(1) | Accepted |
Algorithm Walkthrough
- Read
n, the number of problem sets. We know exactly how many fraction lines must be processed, so the loop can consume precisely those lines. - Initialize
correct = 0andtotal = 0. These variables represent the combined score of all sets processed so far. - For each of the
nlines, read a string such as8/11. Split it at/to obtain the two integer values8and11. - Add the first value to
correctand the second value tototal. Only the current line contributes new information, so previously processed sets never need to be examined again. - After all sets have been processed, print
correctandtotalseparated by/. The accumulated numerator is the total number of correct answers, while the accumulated denominator is the total number of questions.
The invariant is that after processing any prefix of the input, correct equals the total number of correct answers in that prefix and total equals the total number of questions in that prefix. Initially both sums are zero, so the invariant holds before processing anything. Each input line adds exactly its own contribution to both sums, preserving the invariant. After the final line, the prefix is the entire contest, so the two variables are precisely the required output.
Python Solution
import sys
input = sys.stdin.readline
def solve():
n = int(input())
correct = 0
total = 0
for _ in range(n):
a, b = map(int, input().strip().split('/'))
correct += a
total += b
print(f"{correct}/{total}")
if __name__ == "__main__":
solve()
The first line is read as an integer because it determines the number of following records. The two accumulators are initialized once and updated throughout the loop, matching the invariant from the algorithm walkthrough.
For each record, split('/') separates the correct count from the total count. Applying map(int, ...) converts both pieces directly to integers, so no manual character processing is needed.
The code adds the total number of questions rather than the number of wrong answers. This matches the required output format, which prints the combined correct count over the combined total count. If the wrong-answer count is needed conceptually, it is already represented by total - correct.
Python integers automatically expand to accommodate large values, so there is no integer overflow concern even if the sum of the input totals is substantially larger than a 32-bit integer.
There are no array indices or ranges depending on n, so there is no off-by-one issue in the main loop. The loop executes exactly once for every problem set.
Worked Examples
For the first sample, the running totals evolve as follows.
| Step | Input | Correct before | Total before | Correct after | Total after |
|---|---|---|---|---|---|
| 1 | 2/5 |
0 | 0 | 2 | 5 |
| 2 | 4/6 |
2 | 5 | 6 | 11 |
| 3 | 8/11 |
6 | 11 | 14 | 22 |
| 4 | 3/8 |
14 | 22 | 17 | 30 |
| 5 | 1/9 |
17 | 30 | 18 | 39 |
The final state is correct = 18 and total = 39, so the program prints 18/39. Each row demonstrates the invariant directly: the state after processing a row contains exactly the sums of all rows seen so far. The official sample has the same result.
For the second sample, the input includes both perfect performance and zero correct answers.
| Step | Input | Correct before | Total before | Correct after | Total after |
|---|---|---|---|---|---|
| 1 | 6/6 |
0 | 0 | 6 | 6 |
| 2 | 5/6 |
6 | 6 | 11 | 12 |
| 3 | 3/6 |
11 | 12 | 14 | 18 |
| 4 | 0/6 |
14 | 18 | 14 | 24 |
| 5 | 5/8 |
14 | 24 | 19 | 32 |
The fourth row adds zero to the correct count but still adds six to the total count. This is exactly the kind of case that can expose an implementation that incorrectly ignores zero-valued contributions. The final state is 19/32, matching the official sample.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Every problem-set line is read and processed exactly once. |
| Space | O(1) | Only the two running totals and a few temporary parsing variables are stored. |
The solution uses the minimum amount of work needed to inspect the input. Since the statement specifies a 1 second limit and does not provide a visible numerical upper bound for n, avoiding repeated scans is the appropriate choice. Memory usage remains constant apart from the input line currently being processed.
Test Cases
import sys
import io
def solve():
input = sys.stdin.readline
n = int(input())
correct = 0
total = 0
for _ in range(n):
a, b = map(int, input().strip().split('/'))
correct += a
total += b
print(f"{correct}/{total}")
def run(inp: str) -> str:
old_stdin = sys.stdin
old_stdout = sys.stdout
sys.stdin = io.StringIO(inp)
sys.stdout = io.StringIO()
try:
solve()
return sys.stdout.getvalue()
finally:
sys.stdin = old_stdin
sys.stdout = old_stdout
# Provided sample 1
assert run(
"""5
2/5
4/6
8/11
3/8
1/9
"""
) == "18/39\n", "sample 1"
# Provided sample 2
assert run(
"""5
6/6
5/6
3/6
0/6
5/8
"""
) == "19/32\n", "sample 2"
# Minimum-size input
assert run(
"""1
0/1
"""
) == "0/1\n", "minimum size"
# All questions answered correctly
assert run(
"""4
1/1
5/5
100/100
7/7
"""
) == "113/113\n", "all correct"
# All questions answered incorrectly
assert run(
"""3
0/4
0/7
0/10
"""
) == "0/21\n", "all incorrect"
# Boundary-style large input with many records
assert run(
"5\n" + "100000/100000\n" * 5
) == "500000/500000\n", "large values"
| Test input | Expected output | What it validates |
|---|---|---|
1 followed by 0/1 |
0/1 |
Minimum number of problem sets and zero correct answers |
1/1, 5/5, 100/100, 7/7 |
113/113 |
Correct accumulation when every question is answered correctly |
0/4, 0/7, 0/10 |
0/21 |
Zero contributions to the correct-answer total |
Five copies of 100000/100000 |
500000/500000 |
Repeated accumulation and larger integer values |
The test suite also includes both official samples, which verify the complete parsing and accumulation process against the examples supplied by the problem.
Edge Cases
For a single problem set, the algorithm performs exactly one update. With
1
3/7
the initial state is (correct, total) = (0, 0). Processing 3/7 changes it to (3, 7), so the output is 3/7. There is no special case needed for n = 1.
For a set containing no correct answers, consider
1
0/6
The update is correct += 0 and total += 6, producing (0, 6). The output is 0/6. This works because zero is a legitimate contribution and the program never uses truth-value checks such as if a: that could accidentally skip it.
For a perfect set,
1
6/6
the state becomes (6, 6) and the output is 6/6. The denominator is deliberately accumulated from the second number in every fraction. Replacing it with a wrong-answer count would incorrectly produce 6/0.
A mixed case such as
3
2/5
0/3
4/4
produces the states (2, 5), then (2, 8), then (6, 12). The final answer is 6/12. This exercises both zero contributions and a perfect set in the same input and confirms that every line contributes independently to the two sums.
The input syntax itself is another boundary worth handling carefully. A line such as 8/11 must be split on the literal slash before converting the two pieces to integers. The expression map(int, line.split('/')) does exactly that, avoiding integer division and preserving both quantities independently.