← All problems

Nim Game Is XOR Game

Codeforces · Round #1105 (Div. 1) · Problem A

Problem

Given an array AA of nn piles, two players take turns making a move; the last player to make a move wins.

A valid move consists of removing b1b_1 from A[1]A[1], b2b_2 from A[2]A[2], ..., bnb_n from A[n]A[n], where bi0b_i \geq 0 for all ii, at least one bi>0b_i > 0, and

b1b2bn=0.b_1 \oplus b_2 \oplus \cdots \oplus b_n = 0.

Count the number of winning first moves for the first player.

Initial Observations
  1. Write it in binary.
  2. Nim-sum / Sprague-Grundy theorem (find the xor of the numbers).
  3. Construction.
  4. This is a "two-player impartial game," so every game has a nim-sum — can I compute it?
  5. How do I characterize the losing states easily?
  6. Counting?
  7. Make the xor 0?
  8. [Write It Out], [Exploit the Constraints].
  9. Look for a pattern.
IdeaCharacterize the Sprague-Grundy values of the gameNo Solution
Draw from Experience

This is a two-player impartial game: both players have the same set of moves available at any time, they alternate, and the last player to move wins. By well-known results, any such game is equivalent to a single-pile Nim of some size gg — the nim-sum or Sprague-Grundy value of the game. A nim-sum of 00 is a losing state for the player to move; nonzero is winning. You compute it as the minimum excluded value (MEX) of the nim-sums of all states reachable in one move.

I won't go deeper into the theory here, since (spoiler for this Idea) it didn't end up leading to the solution — see the Sprague–Grundy theorem if you want the full story. Had this direction worked out, it would have earned its own Aside with a proof.

Key Question

What is the nim-sum of this game? Can we characterize and compute a pattern for how the Sprague-Grundy theorem applies here?

Examine Examples

I tried small examples. [0 0 0][0\ 0\ 0] is obviously a losing game with nim-sum 00. Any single-pile game is also losing with nim-sum 00: there is no way to remove b>0b > 0 from one pile while keeping the xor of the removals 00 — it contradicts the move constraints. Another family: if every pile has size 11 (single bits), with nn piles, the nim-sum is n/2\lfloor n/2 \rfloor — you can remove any even number of piles (2,4,6,2, 4, 6, \ldots), and induction on the MEX confirms it. And [1 2 3][1\ 2\ 3] is interesting: the xor of all the piles is 00, so you can take everything and win in one move. What makes that so special?

Key Observation

Any game with exactly one non-zero pile (or none) is a losing game for the player to move — there is no valid move at all.

At this point most of my ideas were not leading anywhere. The observations were interesting, but I kept getting stuck. Here are some others that may or may not lead anywhere:

Observation.

The parity of the number of odd piles never changes: every valid move removes values xor-ing to 00, so an even number of the bib_i are odd. (Not sure if this is useful.)

Key Question

Can I mess around with the highest bit? Proofs about nim-sums often peel off the most significant bit of the nim-sum and then make any xor possible in the remaining bits. (Again, not sure if this is useful.)

Generate and Test

I kept getting stuck — making observations about patterns of nim-sums, but nothing stuck. So I tried to guess and check: zooming out, what would a reasonable strategy be if I were playing this game with friends? What could the MEX be, on intuition, and can I prove it? Maybe count the pairs in each bit position and do something special with that? Is it just the number of odd pairs? Admittedly, none of it led anywhere.

I spent way too long in this idea maze of ways to characterize the MEX. It burned most of my time and got me nowhere. The only genuinely useful observation (in hindsight) was that any zero-pile or single-pile game is a losing game. It's not that insightful — it's obvious — but it is a good starting point.

IdeaCan I always kill most of the piles in one move?AC

What possible valid moves can I make? I was stuck, so I decided to get unstuck by looking at more examples.

Examine Examples

I turned back to the sample test cases, just to make forward progress and get my brain out of a rut. [1 4 5 2 6][1\ 4\ 5\ 2\ 6] was the case I looked at. I sorted the items (we can always assume the piles are sorted without loss of generality): [1 2 4 5 6][1\ 2\ 4\ 5\ 6]. I don't know why, but once the piles were sorted, this gave me an idea.

Key Question

In [1 2 4 5 6][1\ 2\ 4\ 5\ 6], can we kill 1,2,4,1, 2, 4, and 55 entirely, and leave the 66 (or something in the pile that used to be 66)?

Key Observation

We can kill the piles 1,2,4,51, 2, 4, 5 and take 22 away from the 66-pile, leaving exactly one pile of size 44. Why? The xor of 1,2,4,51, 2, 4, 5 is exactly 22, so to make the xor of everything we remove equal 00, we just take 22 from the 66-pile. And we already know a single-pile game is a losing state — so this is a winning move.

Key Question

Can we always kill all but one pile in one move? In other words, can we always make a move that forces the other player into a losing game (a game with 00 or 11 piles left)?

Write It Out

Say the piles are [a1,,an][a_1, \ldots, a_n], and try to delete the first n1n-1 entirely: b1=a1,,bn1=an1b_1 = a_1, \ldots, b_{n-1} = a_{n-1}. Since the xor of all removals must be 00, associativity forces bn=a1an1b_n = a_1 \oplus \cdots \oplus a_{n-1}. That's a valid move if and only if bnanb_n \leq a_n. When does that hold? It helps to line the numbers up in binary:

1  =  001
2  =  010
4  =  100
5  =  101
6  =  110

The reason 1245=21 \oplus 2 \oplus 4 \oplus 5 = 2 is 6\leq 6: the most significant bit of the xor comes out 00, while 6=1106 = 110 has that bit on — so the xor is certainly smaller. Does it work with other survivors? Keeping the 55-pile: 1246=151 \oplus 2 \oplus 4 \oplus 6 = 1 \leq 5 — yes. But keeping the 11-pile: 2456=5>12 \oplus 4 \oplus 5 \oplus 6 = 5 > 1 — there is no valid amount to remove. So it works for some survivors and not others.

After working this out and looking at enough examples, I came to the following key observation.

Key Observation

If there is more than one non-zero pile, it is always possible to kill some n1n-1 of the piles entirely and take an amount from the last pile that makes the xor of all removals 00 — leaving exactly 11 (or 00) non-zero piles.

Proof.

Start by xor-ing all the numbers together: X=a1anX = a_1 \oplus \cdots \oplus a_n.

If X=0X = 0, we're done immediately: take every item from every pile. The removals xor to 00, and the next player faces no piles and hence no moves. We win.

Otherwise X0X \neq 0, so some bit of XX is 11; let jj be the most significant such bit. Since bit jj of the xor is 11, at least one of the aia_i must have bit jj set — pick any such index ii^*. We claim the xor of all the numbers except aia_{i^*} — call it Y=XaiY = X \oplus a_{i^*} — satisfies YaiY \leq a_{i^*} (in fact Y<aiY < a_{i^*}):

  • For every bit above jj: that bit of XX is 00, so aia_{i^*} and YY agree on it (they must cancel).
  • On bit jj itself: XX has a 11, so aia_{i^*} and YY differ there — and we chose aia_{i^*} to have bit jj set, so YY has it clear.

So aia_{i^*} and YY match on all higher bits and aia_{i^*} wins on bit jj: Y<aiY < a_{i^*}. Remove all of every other pile and remove YY from pile ii^*: the removals xor to YY=0Y \oplus Y = 0, the move is valid, and pile ii^* survives with aiY>0a_{i^*} - Y > 0 items — a single non-zero pile.

Eureka! This was a really cool observation, and it makes the problem feel much more tractable. First, two quick asides:

Draw from Experience

The proof of the MEX / Sprague-Grundy values in classical Nim leans heavily on the binary representations of the piles and the most-significant-bit of the nim-sum. So this proof wasn't a leap — it rhymed with how nim arguments usually go. For me it was a fairly natural proof once I was pointed at the right question (if you're wondering how I could have gotten here).

Generate and Test

Technically, "we can always kill all but one pile in one move" was just a conjecture — tried out on examples first, proven after. That's Generate and Test. It was a reasonable conjecture to make, and it led to the solution.

Key Observation

Since it is always possible to move the next player into a losing state, any move that doesn't leaves them in a winning state — from which they can do the same to you. So the winning moves are exactly the moves that leave 11 or 00 non-zero piles.

We're now pretty close to a solution: try every move that kills all but one pile, check whether it's valid, and count (plus possibly one more for the move that kills every pile).

Algorithm
Given n and the piles A[1..n]
 
choices = 0                                        # the answer
X = A[1] XOR A[2] XOR ... XOR A[n]                 # xor of all piles, precomputed
 
# for each i: can we kill everything except pile i?
for i in 1..n:                                     # (only meaningful when n >= 2)
    Y = X XOR A[i]                                 # xor of all piles except A[i]
    if Y < A[i]:                                   # remove Y from pile i, all of the rest
        choices += 1
 
if X == 0: choices += 1                            # the take-everything move

Each "kill all but pile ii" move is forced once ii is chosen (the amount removed from pile ii must be exactly YY), so no move is counted twice. With the xor of all piles precomputed, the whole thing is O(n)O(n).

And we're done. Accepted.

Review

The winning moves are exactly the moves that leave at most one non-zero pile, and there are at most n+1n + 1 candidates — one per surviving pile, plus take-everything — each checkable with one xor. The path:

  1. A game with at most one non-zero pile is losing — with one pile, any removal has nonzero xor, so there is no valid move at all. [1]
  2. With more than one non-zero pile, you can always kill all but one pile in a single move. The proof is by construction: xor everything to get XX; if X=0X = 0 take everything; otherwise pick any pile aia_{i^*} with the top bit of XX set — the xor of the others is then strictly smaller than aia_{i^*}, so removing it from pile ii^* (and all of everything else) is a valid move leaving one pile. [3]
  3. Not doing so hands the win away: any other move leaves the opponent two or more piles, from which they can do the same to you. [4]
  4. So the winning moves are exactly the kill-all-but-one moves (plus take-everything when the total xor is 00), and each candidate survivor ii is checked by one comparison: XA[i]<A[i]X \oplus A[i] < A[i].
  5. Count them in O(n)O(n) by precomputing the xor of all piles.
  6. Done...? (Don't forget to take it modulo 998244353998244353.)

References

Problem-solving techniques used:

Examine Examples

Always a good place to start — and at the times I got stuck, it seemed to jog my brain loose and get me unstuck.

Draw from Experience

Useful in the final proof, but it admittedly sent me astray for the first part of the problem: I kept trying to find a complicated characterization via the Sprague-Grundy theorem, which was fine background but not how I should have spent my time.

Generate and Test

Trying "what I think the right answer should be" conjectures or strategies is often useful in construction-style and game-style problems — thinking about what I would actually do if playing this game intuitively. It didn't help all the way, but it moved us along.

Write It Out

A lot of this problem (and the final proof) relied on the binary representations. Keeping it in my head was not helping; writing out the example in binary let me visually see and work the patterns.

Learning points:

Topics: