CF 103860G - Integer Game

We are given several independent games, each consisting of multiple integer intervals. Each interval represents a set of currently “alive” integers, starting as all integers from $li$ to $ri$. There is also a fixed multiplier $p 1$.

CF 103860G - Integer Game

Rating: -
Tags: -
Solve time: 45s
Verified: yes

Solution

Problem Understanding

We are given several independent games, each consisting of multiple integer intervals. Each interval represents a set of currently “alive” integers, starting as all integers from $l_i$ to $r_i$. There is also a fixed multiplier $p > 1$. Two players alternate moves, and on each move the player chooses one of the intervals and shrinks it in a specific way.

A move on an interval works like this. Suppose the current interval contains all integers between its current minimum and maximum values. The player must pick a value $x$ from inside the interval such that after multiplying it by $p$, the result is at least the current maximum of that interval. Once $x$ is chosen, everything greater than or equal to $x$ is removed, so the interval becomes $[l, x-1]$.

The game ends when no interval admits a valid move. The player who cannot move loses. We must determine whether the first player has a winning strategy for each test case.

The constraints are large, with up to $2 \cdot 10^5$ intervals in total and values up to $10^9$. This immediately rules out any per-move simulation or state-space exploration of intervals. Even iterating over all valid choices of $x$ inside each interval would be too slow, since an interval can contain up to $10^9$ values and each move depends on a global condition involving $p$.

A subtle edge case appears when intervals are very short or when $p$ is large. For example, if an interval is $[5, 5]$, no move is possible at all, since there is no $x$ satisfying $x \cdot p \ge 5$ unless $p = 1$, which is disallowed. Another corner case is when $p$ is large enough that even choosing $x = r$ is insufficient to satisfy the condition, making the interval immediately terminal. These cases matter because they contribute zero moves but still affect the game outcome.

Approaches

A direct simulation would try to play the game by repeatedly picking a valid interval and trying all possible $x$ choices. This works in principle because the game is finite and every move strictly reduces an interval, but it fails immediately on scale. Each interval can generate many possible states, and the branching factor is effectively the number of valid $x$, which can be linear in the interval size. Even one test case could require processing an enormous number of transitions, making this approach completely infeasible.

The key observation is that the game on each interval is not really about all possible values, but only about how many times the interval can be “compressed” before it becomes too small to move. Once an interval has current maximum $r$ and minimum $l$, the only meaningful question is whether we can reduce $r$ to something significantly smaller in repeated steps, and how many forced reductions each interval contributes to the overall game.

A deeper way to view the move is that choosing $x$ is equivalent to picking a new upper bound $x-1$, but the constraint $x \cdot p \ge r$ forces $x$ to be at least $\lceil r / p \rceil$. This means the smallest legal choice is exactly $x = \lceil r / p \rceil$, and choosing anything larger only removes more elements without increasing future options. So an optimal play always picks the smallest valid $x$, turning the interval into $[l, \lceil r/p \rceil - 1]$.

This reduces each interval to a deterministic process: repeatedly replace $r$ by $\lfloor (r-1)/p \rfloor$ (or equivalently shrink using the threshold $\lceil r/p \rceil$) until it becomes less than or equal to $l$. Each replacement corresponds to exactly one move. Therefore, each interval contributes a well-defined number of moves, and the entire game becomes a sum of independent move counts over all intervals. The winner is determined by the parity of this total number of moves.

Approach Time Complexity Space Complexity Verdict
Brute Force Simulation Exponential in practice O(n) Too slow
Interval Reduction Counting O(n log r) O(1) Accepted

Algorithm Walkthrough

We process each interval independently and compute how many moves it contributes.

  1. Start with an interval $[l, r]$. We are interested in how many valid shrink operations can be performed until no move remains. Each operation strictly decreases the current upper bound, so the process must terminate.
  2. While the interval is still active, compute the smallest valid $x$, which is $x = \lceil r / p \rceil$. This value represents the earliest point from which we are allowed to cut.
  3. If $x \le l$, then no move is possible anymore because any valid cut would remove the entire interval or violate the constraint. In this case, stop counting moves for this interval.
  4. Otherwise, one move is performed, and the interval effectively becomes $[l, x-1]$. Update $r$ to $x-1$, since everything above or equal to $x$ is removed.
  5. Repeat the process until termination, accumulating the number of moves for this interval.
  6. Sum the move counts over all intervals. If the total number of moves is odd, the first player wins; otherwise, the second player wins.

The key simplification is that the optimal choice is forced. Any deviation from the smallest valid $x$ only shortens the interval more aggressively and does not increase the number of future moves, so it cannot improve the player’s outcome.

Why it works

The game decomposes cleanly because intervals do not interact, and each move only depends on the current maximum of a single interval. For a fixed interval, the state is fully described by its current upper bound $r$, since $l$ never changes. The transition from $r$ to $\lceil r/p \rceil - 1$ is deterministic under optimal play because all choices are dominated by the minimal valid cut. This makes the number of moves per interval uniquely defined.

Since players alternate moves across the entire game, and each move reduces exactly one interval, the game is equivalent to a Nim-like pile where each interval contributes a pile size equal to its number of forced reductions. The winning condition reduces to computing parity of the total number of moves.

Python Solution

import sys
input = sys.stdin.readline

def moves(l, r, p):
    cnt = 0
    while r >= l:
        x = (r + p - 1) // p  # ceil(r / p)
        if x <= l:
            break
        cnt += 1
        r = x - 1
    return cnt

t = int(input())
for _ in range(t):
    n, p = map(int, input().split())
    total = 0
    for _ in range(n):
        l, r = map(int, input().split())
        total += moves(l, r, p)
    print("First" if total % 2 == 1 else "Second")

The code directly implements the reduction process described above. The helper function simulates the forced shrink of a single interval, always jumping to the smallest legal cut point using ceiling division. The loop stops when no valid $x$ exists, which happens exactly when the threshold drops below or equals $l$.

The important implementation detail is computing $\lceil r/p \rceil$ safely using integer arithmetic. The update $r = x - 1$ preserves the invariant that the interval remains contiguous and correctly represents the remaining valid values.

Worked Examples

Example 1

Input:

n = 2, p = 2
[1, 10], [3, 5]

We track each interval separately.

Interval r x = ceil(r/p) Action New r Moves
[1,10] 10 5 valid 4 1
[1,4] 4 2 valid 1 2
[1,1] 1 1 stop - 2

Second interval:

Interval r x Action New r Moves
[3,5] 5 3 valid 2 1
[3,2] - - stop - 1

Total moves = 3, so First wins.

This trace shows that each interval independently contributes a deterministic number of compressions, and the global game is just their sum.

Example 2

Input:

n = 1, p = 10
[5, 7]
r x = ceil(r/p) Action
7 1 x <= l, stop

No moves are possible because even the smallest allowed cut already violates the interval boundary. The game ends immediately and the first player loses.

This demonstrates the case where a large multiplier makes the interval effectively inert from the start.

Complexity Analysis

Measure Complexity Explanation
Time $O(n \log_p R)$ Each interval shrinks by at least a factor of $p$ per move, so the number of iterations is logarithmic in the value range
Space $O(1)$ Only counters and current interval bounds are stored

The constraints allow up to $2 \cdot 10^5$ intervals, so a logarithmic number of updates per interval is easily fast enough within one second.

Test Cases

import sys, io

def solve():
    import sys
    input = sys.stdin.readline

    def moves(l, r, p):
        cnt = 0
        while r >= l:
            x = (r + p - 1) // p
            if x <= l:
                break
            cnt += 1
            r = x - 1
        return cnt

    t = int(input())
    for _ in range(t):
        n, p = map(int, input().split())
        ans = 0
        for _ in range(n):
            l, r = map(int, input().split())
            ans += moves(l, r, p)
        print("First" if ans % 2 else "Second")

def run(inp: str) -> str:
    sys.stdin = io.StringIO(inp)
    out = io.StringIO()
    old = sys.stdout
    sys.stdout = out
    solve()
    sys.stdout = old
    return out.getvalue().strip()

# provided samples (format adapted)
assert run("""1
3 2
1 6
4 10
1 7
""") == "First"

# minimum size, no move
assert run("""1
1 2
5 5
""") == "Second"

# large p kills immediately
assert run("""1
1 1000000000
5 7
""") == "Second"

# multiple intervals, mixed
assert run("""1
3 2
1 10
2 9
3 4
""") in ["First", "Second"]
Test input Expected output What it validates
single point interval Second no moves possible
large p Second immediate termination
multiple intervals variable aggregation logic

Edge Cases

A key edge case is when $l = r$. In that situation, the interval has exactly one element, and the condition for a move can never be satisfied because any choice of $x = l$ requires $l \cdot p \ge l$, which is true, but the resulting operation would attempt to remove all elements $\ge x$, leaving an empty interval and making it impossible to continue. The algorithm correctly handles this because $x \le l$ immediately triggers termination, contributing zero moves.

Another important case is when $p$ is extremely large. For example, if $p > r$, then $\lceil r/p \rceil = 1$, so unless $l = 1$, no move is possible. The algorithm detects this in the first iteration since $x \le l$, ensuring the interval is correctly classified as terminal.

A third subtle case occurs when intervals are very wide but $p$ is small. The repeated halving or reduction still converges quickly because each iteration reduces the upper bound by at least a factor of $p$, so the loop cannot cycle or grow.