CF 1153A - Serval and Bus
Serval is going to the bus station at a specific time t. There are n bus routes, each with a first bus arriving at si minutes and subsequent buses every di minutes. Serval will take the first bus that comes after or exactly at time t.
Rating: 1000
Tags: brute force, math
Solve time: 1m 43s
Verified: yes
Solution
Problem Understanding
Serval is going to the bus station at a specific time t. There are n bus routes, each with a first bus arriving at s_i minutes and subsequent buses every d_i minutes. Serval will take the first bus that comes after or exactly at time t. If multiple buses arrive at the same earliest time, any one of those routes is acceptable. The task is to determine which bus route Serval will board.
The input consists of n and t, followed by n pairs (s_i, d_i) representing the first arrival time and interval of each bus route. The output is a single integer representing the 1-based index of the chosen bus route.
The constraints are moderate: n is at most 100, and times can go up to 10^5. A brute-force check across each bus route is feasible because even if we iterated minute by minute, the number of operations would be within the limit. Edge cases include the first bus of a route arriving exactly at t, routes where all buses arrive after t, or multiple routes sharing the earliest bus after t. For instance, if t=2 and two routes have buses at times [2,4,6] and [2,5,8], both are valid answers.
Approaches
The naive approach is to generate all arrival times for each bus route until we reach or surpass t and then select the earliest among them. This works because n is small and the intervals d_i are bounded. However, constructing all bus times is unnecessary and can be avoided using simple arithmetic.
The key insight is that for a route starting at s_i with interval d_i, the first bus Serval can catch occurs at s_i if s_i >= t. Otherwise, we can compute the first bus after t directly as the smallest multiple of d_i added to s_i that is at least t. Mathematically, this is s_i + ceil((t - s_i)/d_i) * d_i. Using integer arithmetic, we can compute this with (t - s_i + d_i - 1) // d_i to avoid floating point operations. This reduces the problem to scanning each bus route once and computing its earliest catchable bus, making the solution O(n) in time.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force (generate all times) | O(n * max((t - s_i)/d_i)) | O(1) | Works for small t, inefficient for large intervals |
| Optimal (direct calculation) | O(n) | O(1) | Accepted |
Algorithm Walkthrough
- Read
nandt. - Initialize two variables:
best_timeto a very large value (to track the earliest bus) andbest_routeto -1. - For each bus route index
ifrom 1 ton, reads_iandd_i. - If
s_i >= t, set the next bus for this route tos_i. - Otherwise, calculate how many intervals we need to wait after
s_ito reach at leastt. This is(t - s_i + d_i - 1) // d_i. Multiply this byd_iand adds_ito get the earliest bus time for this route. - If this bus time is less than
best_time, updatebest_timeand setbest_routetoi. - After checking all routes, print
best_route.
Why it works: The algorithm maintains the invariant that best_time always holds the earliest bus Serval can catch among all processed routes. By computing the first catchable bus for each route using integer arithmetic, we guarantee that we never miss the actual earliest bus, and the final best_route is guaranteed to be correct.
Python Solution
import sys
input = sys.stdin.readline
n, t = map(int, input().split())
best_time = float('inf')
best_route = -1
for i in range(1, n + 1):
s, d = map(int, input().split())
if s >= t:
next_bus = s
else:
wait = (t - s + d - 1) // d
next_bus = s + wait * d
if next_bus < best_time:
best_time = next_bus
best_route = i
print(best_route)
The code reads input efficiently using sys.stdin.readline. The loop computes the earliest catchable bus for each route. The (t - s + d - 1) // d formula ensures we round up when the interval does not divide evenly. Updating best_time and best_route only when a strictly earlier bus is found avoids ambiguity, and using 1-based indexing matches the problem's expected output.
Worked Examples
Sample 1
Input:
2 2
6 4
9 5
| Route | s_i | d_i | next_bus | best_time | best_route |
|---|---|---|---|---|---|
| 1 | 6 | 4 | 6 | 6 | 1 |
| 2 | 9 | 5 | 9 | 6 | 1 |
The earliest bus is route 1 at time 6. Serval boards route 1.
Sample 2
Input:
3 2
2 2
2 3
2 4
| Route | s_i | d_i | next_bus | best_time | best_route |
|---|---|---|---|---|---|
| 1 | 2 | 2 | 2 | 2 | 1 |
| 2 | 2 | 3 | 2 | 2 | 1 |
| 3 | 2 | 4 | 2 | 2 | 1 |
All routes have the first bus at 2. Any route from 1 to 3 is valid; the algorithm picks the first encountered minimum, route 1.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Each route is scanned once, and the arithmetic for next bus is O(1) |
| Space | O(1) | Only a few variables are maintained; no large data structures needed |
Given n ≤ 100, this solution runs in a fraction of a millisecond. Memory usage is negligible compared to the 256 MB limit.
Test Cases
import sys, io
def run(inp: str) -> str:
sys.stdin = io.StringIO(inp)
n, t = map(int, input().split())
best_time = float('inf')
best_route = -1
for i in range(1, n + 1):
s, d = map(int, input().split())
if s >= t:
next_bus = s
else:
wait = (t - s + d - 1) // d
next_bus = s + wait * d
if next_bus < best_time:
best_time = next_bus
best_route = i
return str(best_route)
# Provided samples
assert run("2 2\n6 4\n9 5\n") == "1", "sample 1"
assert run("3 2\n2 2\n2 3\n2 4\n") == "sample 2"
# Custom cases
assert run("1 1\n1 1\n") == "1", "single route catches immediately"
assert run("2 10\n1 3\n2 4\n") == "1", "earliest bus requires multiple intervals"
assert run("3 5\n2 2\n3 3\n5 1\n") == "3", "exact match at t"
assert run("3 7\n2 2\n3 3\n4 4\n") == "1", "multiple options, first min picked"
| Test input | Expected output | What it validates |
|---|---|---|
| 1 1\n1 1 | 1 | Single route catches immediately |
| 2 10\n1 3\n2 4 | 1 | Waiting multiple intervals, check calculation |
| 3 5\n2 2\n3 3\n5 1 | 3 | Route exactly at t is chosen |
| 3 7\n2 2\n3 3\n4 4 | 1 | Multiple routes arrive at same next bus; first minimum selected |
Edge Cases
If t is before the first bus of a route, s_i >= t, the next bus is s_i. For example, t=1, s=5, d=3 gives next_bus=5. The algorithm correctly identifies this as the earliest bus. When multiple routes have the same earliest next bus, the algorithm picks the first encountered minimum. For t=2 and buses [2,4], [2,5], [2,6], best_time becomes 2 at route 1, and the output is route 1. This satisfies the problem because any route with the earliest bus is acceptable.