Source: USAMO-2021-P3
Category: Operations and Strategies

Problem: Let $n \\geq 2$ be an integer. An $n \\times n$ board is initially empty. Each minute, you may perform one of three moves: • If there is an L-shaped tromino region of three cells without stones on the board (see figure; rotations not allowed), you may place a stone in each of those cells. • If all cells in a column have a stone, you may remove all stones from that column. • If all cells in a row have a stone, you may remove all stones from that row. For which $n$ is it possible that, after some non-zero number of moves, the board has no stones?

Answer: The answer is $3 \\mid n$

Reference solution:
The answer is $n$ such that $3 \mid n$.

**Construction for $3 \mid n$:**
For $n=3$, a fairly straightforward sequence of moves exists to return to the empty board. This construction can then be extended to any $n$ such that $3 \mid n$.

**Polynomial-based proof of converse:**
Assume for contradiction that $3 \nmid n$. We will show the task is impossible even if we allow stones to have real weights in our process. 

A valid elimination corresponds to a non-zero polynomial $P \in \mathbb{R}[x,y]$ such that
\begin{align*}
\deg_x P &\le n-2 \\
\deg_y P &\le n-2 \\
(1+x+y) P(x,y) &\in \left\langle 1+x+\dots+x^{n-1}, \; 1+y+\dots+y^{n-1}\right\rangle.
\end{align*}
(Here $\langle \dots \rangle$ is an ideal of $\mathbb{R}[x,y]$.) 

In particular, if $S$ is the set of $n$-th roots of unity other than $1$, we should have 
\[
(1+z_1+z_2) P( z_1, z_2 ) = 0
\]
for any $z_1 , z_2 \in S$. Since $3 \nmid n$, it follows that $1+z_1+z_2 \neq 0$ always. So $P$ vanishes on $S \times S$, a contradiction to the bounds on $\deg P$ (by, say, the Combinatorial Nullstellensatz on any nonzero term).

Grading guidelines:
(Partial) 1. Established the correct invariant/encoding of a position by a polynomial (or equivalent linear functional) so that placing an L-tromino adds a translate of 1+x+y and clearing a full row/column corresponds to adding a multiple of 1+x+…+x^{n-1} or 1+y+…+y^{n-1}. 2. Proved the key roots-of-unity test: for any n-th roots of unity z1,z2≠1 one must have (1+z1+z2)P(z1,z2)=0, and observed that if 3∤n then 1+z1+z2≠0 for all such z1,z2. 3. Gave a correct explicit move sequence returning to empty for n=3, or clearly reduced the construction for general n divisible by 3 to a tiling/concatenation of a 3×3 gadget. (Almost) 1. Proved the impossibility for 3∤n via the polynomial/roots-of-unity method, but left a minor gap in justifying why existence of a nontrivial return-to-empty sequence yields a nonzero P with deg_x,deg_y≤n−2 in the stated ideal condition. 2. Completed the vanishing-on-S×S argument for 3∤n, but the final contradiction (e.g., the application of Combinatorial Nullstellensatz / degree-counting to deduce P≡0) is insufficiently justified or misses one boundary degree case. 3. Gave a correct construction for all n with 3|n and a correct outline of the converse, but omitted the check that rotations are not allowed in the L-move (or handled only one orientation) while claiming the full result.

Construction task:
For $n = 81$, provide an explicit sequence of moves to completely empty the board after a non-zero number of moves.

Construction format requirements:
- Output a single Python expression that evaluates to a list of moves.
- Each move should be a tuple of one of the following forms:
  - `("place", r, c)`: Places an L-tromino such that it covers the cells `(r, c)`, `(r-1, c)`, and `(r, c+1)`. (Here `r` is the 0-based row index and `c` is the 0-based column index, $0 \le r, c < 81$).
  - `("row", r)`: Removes all stones from row `r` (requires row `r` to be completely full).
  - `("col", c)`: Removes all stones from column `c` (requires column `c` to be completely full).
- The board is $81 \times 81$, 0-indexed.
- The sequence must be valid: you can only place an L-tromino if all three of its cells are currently empty, and you can only clear a row/column if it is completely full.
- After all moves are executed, the board must be completely empty, and the sequence of moves must be non-empty.
- The output must be a single, valid Python expression (e.g., using list concatenations and comprehensions).
- Put ONLY the Python expression inside the `<construct>` block, with no formatting, no markdown code blocks, and no explanations.

Reference construction:
[("place", 3*i+1, 3*j+1) for i in range(27) for j in range(27)] + [("place", 3*i+2, 3*j) for i in range(27) for j in range(27)] + [("row", 3*i+1) for i in range(27)] + [("place", 3*i+1, 3*j) for i in range(27) for j in range(27)] + [("col", 3*j) for j in range(27)] + [("col", 3*j+1) for j in range(27)]

Verifier code:
import sys

def verify():
    # Read the raw payload from stdin
    raw_payload = sys.stdin.read().strip()
    if not raw_payload:
        print("Empty input.")
        return

    # Evaluate the payload as a Python expression
    try:
        moves = eval(raw_payload)
    except Exception as e:
        print(f"Failed to parse input: {e}")
        return

    # Verify that the parsed object is a non-empty list of tuples
    if not isinstance(moves, list):
        print("Input must evaluate to a list.")
        return
    if len(moves) == 0:
        print("The sequence of moves must be non-empty.")
        return

    # Initialize an 81x81 boolean matrix to False (empty board)
    board = [[False for _ in range(81)] for _ in range(81)]

    # Iterate through each move in the list
    for idx, move in enumerate(moves):
        if not isinstance(move, tuple):
            print(f"Move at index {idx} is not a tuple: {move}")
            return
        if len(move) == 0:
            print(f"Move at index {idx} is empty.")
            return
        
        op = move[0]
        if op == "place":
            if len(move) != 3:
                print(f"Move at index {idx} has invalid length for 'place': {move}")
                return
            _, r, c = move
            if type(r) is not int or type(c) is not int:
                print(f"Move at index {idx} has non-integer coordinates: {move}")
                return
            if not (1 <= r < 81 and 0 <= c < 80):
                print(f"Move at index {idx} has out-of-bounds coordinates for 'place': {move}")
                return
            if board[r][c] or board[r-1][c] or board[r][c+1]:
                print(f"Move at index {idx} attempts to place on non-empty cells: {move}")
                return
            # Place the L-tromino
            board[r][c] = True
            board[r-1][c] = True
            board[r][c+1] = True
            
        elif op == "row":
            if len(move) != 2:
                print(f"Move at index {idx} has invalid length for 'row': {move}")
                return
            _, r = move
            if type(r) is not int:
                print(f"Move at index {idx} has non-integer row index: {move}")
                return
            if not (0 <= r < 81):
                print(f"Move at index {idx} has out-of-bounds row index: {move}")
                return
            if not all(board[r][c] for c in range(81)):
                print(f"Move at index {idx} attempts to clear row {r} which is not completely full.")
                return
            # Remove all stones from row r
            for c in range(81):
                board[r][c] = False
                
        elif op == "col":
            if len(move) != 2:
                print(f"Move at index {idx} has invalid length for 'col': {move}")
                return
            _, c = move
            if type(c) is not int:
                print(f"Move at index {idx} has non-integer column index: {move}")
                return
            if not (0 <= c < 81):
                print(f"Move at index {idx} has out-of-bounds column index: {move}")
                return
            if not all(board[r][c] for r in range(81)):
                print(f"Move at index {idx} attempts to clear column {c} which is not completely full.")
                return
            # Remove all stones from column c
            for r in range(81):
                board[r][c] = False
                
        else:
            print(f"Move at index {idx} has an invalid operation: {move}")
            return

    # After processing all moves, verify that every cell in the board is False
    for r in range(81):
        for c in range(81):
            if board[r][c]:
                print(f"After all moves, the board is not empty. Cell ({r}, {c}) contains a stone.")
                return
                
    print("True")

if __name__ == "__main__":
    verify()