๐ค Why Advanced Strategy Matters: Beyond Standard Nim
You've mastered Nim. You know Grundy numbers. You can solve Stone Games in your sleep. Now it's time to level up. The problems in this article are the final bossof competitive programming game theory โ the ones that separate "I know game theory" from "I understand game theory".
What makes these problems different?
Wythoff's Game โ The game that requires the golden ratio ฯ. Yes, you read that right. The Fibonacci sequence's cousin makes an appearance in a two-pile game.
Flip Game II โ A string-based impartial game where moves break the string into independent subgames. Classic Sprague-Grundy application with XOR of Grundy numbers.
Palindrome Games โ Remove palindromic subsequences. The "easy" version is a brainteaser; the "hard" version requires interval DP on palindrome structure.
Cat & Mouse โ A graph-based game with three possible outcomes: mouse win, cat win, or draw. Requires state-space BFS and backward induction.
Even/Odd Strategy โ Parity-based reasoning that often collapses to simple checks: count evens, check totals, pattern matching.
Tip
๐ก The Big Picture: Every game problem reduces to one of these patterns:
Cold/Hot positions โ Mark losing/winning states (Wythoff, Nim)
Grundy + XOR โ Decompose into independent subgames (Flip Game II, Grundy's Game)
Interval DP โ dp[l][r] for optimal play on contiguous segments (Palindrome Game Hard, Stone Games)
Graph state space โ (pos1, pos2, turn) triples with BFS (Cat & Mouse, World of Darkraft)
Parity / counting โ Simple even/odd or counting arguments (Even Number Addicts, Circle Game)
1. Wythoff's Game โ Betty Sequences & the Golden Ratio
Problem: Two piles of stones. On each turn, a player can either: (a) remove any positive number of stones from one pile, OR (b) remove the same positive number of stones from both piles. The player who takes the last stone wins.
Note
๐ญ Real-World Analogy: Imagine two stacks of pancakes. On your turn, you can either eat some pancakes from one stack, OR eat the same number from BOTH stacks. The person who eats the last pancake wins. This extra "both piles" move is what makes Wythoff fundamentally different from Nim!
๐ Real-Time Thinking โ What Do I Know?
"OK, this is like Nim but with an extra move: remove equal from both. In standard Nim, the cold positions (P-positions) are when XOR of pile sizes = 0. But here, XOR doesn't tell the whole story because of the 'remove equal from both' move. Let me think about small positions..."
"For (0,0): it's terminal โ no moves, losing position. Base case."
"For (1,0) or (0,1): can remove one stone from the non-zero pile โ reaches (0,0). So (1,0) and (0,1) are winning."
"For (1,1): can remove one from both โ reaches (0,0). So (1,1) is winning."
"For (1,2): Can remove 1 from pile A โ (0,2). Can remove 1 from both โ (0,1). Can remove 2 from pile B โ (1,0). But wait... all these reach winning positions for the opponent? Let me check: (0,2) is winning (remove 2 from pile B), (0,1) is winning, (1,0) is winning. So (1,2) is LOSING! Found the first cold position!"
"Now (2,2): remove 2 from both โ (0,0). That's a win. So (2,2) is winning."
"The cold positions follow a pattern: (1,2), (3,5), (4,7), (6,10), (8,13)... Wait โ these involve the golden ratio! Let me check: aโ = โkยทฯโ, bโ = aโ + k where ฯ = (1+โ5)/2."
The Betty Sequence Connection
Wythoff's Game is famous because its cold positions follow Betty sequencesinvolving the golden ratio ฯ = (1+โ5)/2 โ 1.618:
These two sequences partition the natural numbers โ every positive integer appears EXACTLY ONCE across both sequences! This is known as Beatty's theorem.
The Strategy
Given a position (a, b) with a โค b:
Let k = b - a (the difference between piles)
Compute aโ = โk ยท ฯโ where ฯ = (1+โ5)/2
If a == aโ, this is a cold (losing) position โ first player loses
Otherwise it's a hot (winning) position โ first player can move to a cold position
Edge Cases
a > b: Swap so a โค b first. The position (b, a) has the same status.
a = 0, b = 0: Terminal cold position (k = 0, aโ = 0).
Large k: Compute โkยทฯโ carefully with floating point. ฯ = (1+โ5)/2, use Math.floor(k * (1 + Math.sqrt(5)) / 2).
Integer overflow: kยทฯ can be large. In C++, use int a_k = k * (1.0 + sqrt(5.0)) / 2.0;.
๐ Edge Cases to Consider
Equal piles (a = b): k = 0, aโ = 0. Cold only if both are 0. So any equal non-zero pile is winning (remove all from both).
One empty pile: If a = 0 and b > 0, it's winning (remove b stones from the non-empty pile).
Small positions: (1,2), (3,5), (4,7), (6,10) are cold. Everything else up to these values is hot.
Precision: For k up to 10โน, double precision is sufficient for the floor computation.
๐ค The Decision: Can I Reach a Cold Position?
"I'm at a hot position. I need exactly ONE move that reaches a cold position. I can either reduce one pile, or reduce both equally. The cold positions follow (aโ, bโ). So I need to check: can I reduce pile A to aโ for some k, or reduce both to reach a cold (aโ, bโ)?"
This is the choose/not-choose decision: I choose to move to the cold position whose difference k = b - a, if a > aโ I reduce pile A to aโ; if a < aโ I need a different move.
Key Insight
๐ The Golden Ratio Insight: Wythoff's Game is the ONLY impartial game where the cold positions follow an irrational sequence. The golden ratio ฯ appears because the sequence must partition the natural numbers โ a consequence of Beatty's theorem. This is why every integer appears exactly once across all cold positions: the sets {โkยทฯโ} and {โkยทฯยฒโ} partition โโบ.
ProblemEmbed: wythoffs-game
2. Flip Game II โ Sprague-Grundy on Strings
Problem: Given a string containing only '+' and '-'. Two players take turns flipping two consecutive '++' into '--'. The player who cannot make a move loses. Determine if the first player can force a win.
Note
๐ฎ Real-World Analogy: Imagine a row of light switches, all initially ON (represented by '+'). On your turn, you can flip any two adjacent ON switches to OFF. The person who makes the last move wins. Some switches may already be OFF ('-'), blocking certain moves!
๐ Real-Time Thinking โ What Do I Know?
"This is an impartial combinatorial game. Each move flips two adjacent '+' to '--', which effectively splits the string into independent left and right segments. The '--' acts as a barrier โ segments separated by already-flipped zones don't interact."
"Since this decomposes into independent subgames, I can use the Sprague-Grundy theorem: Grundy(entire game) = XOR of Grundy(each contiguous '++..+' segment). A position is winning iff Grundy โ 0."
"For a contiguous segment of '+' of length n, flipping at position i (0-indexed) breaks it into two segments: left has length i-1, right has length n-i-2. So Grundy(n) = mex of { Grundy(i-1) โ Grundy(n-i-2) | for all valid i }."
The Sprague-Grundy Formulation
Let's derive this step by step:
A contiguous run of n '+' signs forms an impartial game.
Flipping positions [i, i+1] (0 โค i โค n-2) replaces the run of n with two runs: length i (left) and length n-i-2 (right).
The Grundy of the resulting position = Grundy(left) โ Grundy(right).
Large maxN: Precompute Grundy up to n. The values become periodic after n=10 or so โ use this for optimization.
๐ค The Decision: Which Flip Maximizes My Chances?
"I need to pick a flip such that the XOR of the resulting Grundy numbers is 0 (making it a losing position for my opponent). So I compute xorSum of all segments. I need to find a flip where: xorSum โ Grundy(current) โ Grundy(left) โ Grundy(right) = 0. This is the choose/not-choose framework: I choose the flip that makes the total XOR zero."
Tip
โก Optimization: The Grundy sequence for Flip Game II is periodic: G(n) = 0 for n = 0,1,6,11..., G(n) = 1 for n = 3,4,7,8..., G(n) = 2 for n = 5,9..., G(n) = 3 for n = 10,15... Precompute up to max segment length and cache for multiple test cases.
ProblemEmbed: flip-game-ii
3. Palindrome Games โ Easy & Hard
Problem (Easy): Given a string s containing only 'a' characters, two players take turns removing a palindromic subsequence (not necessarily contiguous!). The player who cannot move (string is empty) loses. Who wins?
Problem (Hard): Same rules, but the string contains BOTH 'a' and 'b' characters. Who wins?
Note
๐ญ Real-World Analogy: Imagine a row of colored tiles. On your turn, you can remove any set of tiles that forms a palindrome (reading the same forwards and backwards) โ but they DON'T have to be next to each other! You can pick any tiles at any positions that form a palindrome. The player who removes the last tile wins.
๐ Real-Time Thinking โ The Easy Version
"The string contains ONLY 'a's. A palindromic subsequence... wait, ANY subsequence of identical characters is a palindrome! 'aaa...a' is always a palindrome. So Alice can remove ALL characters in her first move (the entire string is a palindrome). She wins instantly unless the string is empty."
Answer (Easy): If s is empty โ Bob wins. Otherwise โ Alice wins (removes entire string in one move).
๐ Real-Time Thinking โ The Hard Version
"Now we have both 'a' and 'b'. Let's think..."
"If the entire string s is itself a palindrome, Alice can remove it all in one move and win. So the only interesting case is when s is NOT a palindrome."
"Bob's winning strategy: After Alice's first move, there are at most 2 distinct characters left (since only 'a' and 'b' exist). If the remaining characters are all the same โ palindrome โ Bob's turn โ Bob removes all and wins. But wait..."
"Actually, there's a known result: For binary strings (only 'a' and 'b'), the second player (Bob) wins if and only if the string is NOT a palindrome and the string has an even number of characters? No โ let me think more carefully."
The Actual Result
For the Palindrome Game with binary strings:
If s is empty: First player loses (no moves).
If s is a palindrome: First player wins (remove entire string).
If s is NOT a palindrome:
If s contains only one character type โ it's always a palindrome (all same chars). Contradiction โ this case is covered above.
If s contains both 'a' and 'b' and is NOT a palindrome โ Bob can ALWAYS win by optimal play.
Bob's Winning Strategy (when s is not a palindrome)
If Alice removes a set that leaves only one character type โ palindrome โ Bob removes all and wins.
If Alice leaves both character types, Bob can always mirror or counter to eventually leave a non-palindrome for Alice that she can't fully clear.
The key insight: with 2 character types, Bob can always force a win when the initial string is not a palindrome.
๐ Edge Cases to Consider
Empty string: First player loses regardless.
Single character: Always a palindrome โ first player wins.
All same characters: Palindrome โ first player wins.
Two characters, alternating like "ab": Not a palindrome โ Bob wins.
"aba": Palindrome โ Alice wins (remove all).
"aab": Not a palindrome โ Bob wins.
The DP Approach for Hard Version
For the interval DP solution on Palindrome Game Hard, we compute dp[l][r] = whether the current player can force a win on substring s[l..r]:
Warning
โ ๏ธ Common Pitfall: Don't confuse "palindromic subsequence" with "palindromic substring"! A subsequence can skip characters. This makes the Easy version trivial (remove everything at once) but the Hard version surprisingly deep.
ProblemEmbed: palindrome-game-easy
ProblemEmbed: palindrome-game-hard
4. Cat & Mouse โ Graph Game with State Space Analysis
Problem: You are given a directed graph. The mouse starts at node 1, the cat at node 2. Node 0 is a safe node (the mouse wins if it reaches 0). The mouse moves first. Players alternate moving along edges. The cat wins if it catches the mouse (same node). The game may go on forever (draw). Determine the outcome.
Note
๐ฑ๐ญ Real-World Analogy: A cat and mouse are in a house with connected rooms. The mouse moves first. The mouse wants to reach the exit (room 0) while avoiding the cat. The cat wants to catch the mouse. If both play optimally, does the mouse escape, does the cat catch it, or do they run forever? Move by move, the game state is (mouseRoom, catRoom, whoseTurn).
๐ Real-Time Thinking โ What Do I Know?
"This is a partisan game on a graph โ but actually it's impartial because both players have the same move options (follow edges). The twist is: there are THREE possible outcomes (mouse win, cat win, draw), not just two!"
"I can model this as a state space graph where each state is (mousePos, catPos, turn). The game has at most n ร n ร 2 states (where turn = 0 for mouse, 1 for cat). For n โค 50, that's at most 5000 states โ manageable for BFS/DP."
"Terminal states: Mouse wins if mousePos = 0 (safe node). Cat wins if mousePos = catPos."
The Algorithm: Backward Induction with BFS
We use a technique called retrograde analysis (backward induction):
Use a queue to propagate: when a state is determined, its predecessors may become determined too.
Mouse's turn: If ANY move leads to MOUSE WIN โ state is MOUSE WIN. If ALL moves lead to CAT WIN โ state is CAT WIN.
Cat's turn: If ANY move leads to CAT WIN โ state is CAT WIN. If ALL moves lead to MOUSE WIN โ state is MOUSE WIN.
States that remain unknown after propagation are DRAW (cycle forever).
๐ Edge Cases to Consider
Mouse starts at safe node (0): Immediate MOUSE WIN. No moves needed.
Cat starts at same node as mouse: Immediate CAT WIN.
No edges from a node: If mouse is at a dead end and not safe, it can't move. If cat is at a dead end, it can't move.
Graph has cycles: The algorithm correctly detects draws from states that can't be resolved.
Disconnected graph: Cat may never reach the mouse โ potential draw.
๐ค The Decision: Minimax on the State Graph
"On my turn, I evaluate all my possible moves. If I'm the mouse, I choose a move that leads to MOUSE WIN (if one exists). If I'm the cat, I choose a move that leads to CAT WIN (if one exists). This is pure minimax on the state graph โ the choose/not-choose framework extended to three outcomes."
Key Insight
๐ The State Space Insight: The key trick is converting a graph game into a BFS on a meta-graph of (pos1, pos2, turn) states. This transformation is used in World of Darkraft and similar problems. Always ask: "Can I model this as a state machine with a small number of dimensions?"
ProblemEmbed: cat-and-mouse
4.1 World of Darkraft โ State Space on RPG Stats
Problem: Two players have RPG characters with stats (attack, defense, health, mana, etc.). On each turn, a player can perform an action (attack, heal, buff, etc.) that changes the game state. Determine the winner under optimal play.
๐ Real-Time Thinking โ What Do I Know?
"This is another state space game like Cat & Mouse. Each game state is defined by (player1HP, player2HP, cooldowns, mana, etc.). But the state space can be huge! I need to find patterns or reduce dimensions."
"Key observation: Many RPG game states have a limited number of meaningful actions. If I can bound the total number of states (e.g., total HP โค 1000, mana โค 100), I can use DP/memoization on the state space. The minimax rule applies: I choose the action that maximizes my winning chance, assuming my opponent minimizes it."
State Space Reduction
Identify invariant properties: Some stats may be bounded or monotonic (HP only decreases).
Symmetry reduction: Many states are symmetric โ prune by canonical representation.
Turn parity: If the total number of possible actions is limited, the game must end within some bound.
Warning
โ ๏ธ Important: The state space for World of Darkraft can explode exponentially. Always look for bounds (e.g., max turns because HP decreases monotonically, or mana caps actions). If unbounded, look for a pattern or formula instead of DP.
ProblemEmbed: world-of-darkraft
4.2 Circle Game โ Symmetric Strategy Stealing
Problem: There are n points arranged in a circle. Two players take turns connecting two adjacent unconnected points with an edge. The player who completes a triangle wins (or loses, depending on variant). Determine the winner.
๐ Real-Time Thinking โ What Do I Know?
"This is a positional game on a cycle. Symmetry often plays a key role. If n is odd, the first player can use a strategy stealing argument: mirror the opponent's move across the center. If n is even, the second player might have a symmetric strategy."
Key Insight: Symmetry
For the circle game (and many symmetric board games), the strategy-stealing argumentoften proves the first player can always win โ but it doesn't tell us HOW. For specific variants:
Odd number of points: First player picks a point, then mirrors opponent's moves across the diameter through that point.
Even number of points: Second player can mirror across the center if the first player's move was not central.
Triangle completion loses: Avoid creating a path of length 2 where the third edge would complete a triangle.
Key Insight
๐ The Symmetry Principle: In symmetric games, the optimal strategy is often "copy your opponent's move in the symmetric position." This is called a mirror strategyand it guarantees the second player can always match the first player's moves.
Many game theory problems reduce to simple parity (even/odd) checks orcounting patterns. These are the "hidden gem" patterns that experienced competitive programmers spot immediately.
Even Number Addicts
Problem: There are n numbers. Two players take turns picking numbers. Alice wants the sum of her numbers to be even. Bob wants the sum of his numbers to be even too (or Alice says "I can make my sum even" at the end). Determine who wins under optimal play.
๐ Real-Time Thinking โ What Do I Know?
"Parity! I don't care about the exact values โ only whether each number is even or odd. Even numbers don't change the sum parity. Odd numbers flip it. So this is about controlling the number of odd numbers each player ends up with."
The Solution
Let's denote:
evens = count of even numbers
odds = count of odd numbers
๐ Edge Cases to Consider
All evens: Alice's sum is always even regardless of picks โ Alice wins.
All odds, n is odd: Alice gets ceil(n/2) odds, which is odd โ sum is odd โ Alice loses if she needs even.
Mixed evens and odds: Alice can use evens strategically to skip picking odds.
Nullify Matrix
Problem: Given an mรn binary matrix, two players take turns. On your turn, you pick a row or column that has at least one 1 and nullify it (set all its elements to 0). The player who cannot move loses. Determine who wins.
๐ Real-Time Thinking โ What Do I Know?
"This is a Nim-like impartial game where each move removes a set of 1's. But there's a crucial observation: picking a row nullifies that entire row, and picking a column nullifies that entire column. This is equivalent to the game of Dawson's Kaylesor turning-turtles on a matrix. But actually โ there's a simpler view: each 1 is a token, and a move removes all tokens in a row or column. This is isomorphic to the game of Dawson's Kayles only if we consider that overlapping rows/columns interact."
"Key insight: The game is equivalent to having two piles (rows and columns). Each move picks either a row or column that still has a 1. But actually, it reduces to: if there's at least one 1 in the matrix, the first player usually wins because they can pick the row or column with the most 1's. But the optimal play is deeper..."
Warning
โ ๏ธ Nullify Matrix is Deeper Than It Looks: Nullifying a row removes 1's that overlap with multiple columns, changing the available column moves. This makes it apartizan game on a bipartite graph. The full solution often usesGrundy numbers on the matrix's bipartite graph where rows and columns are nodes and 1's are edges.
Substring Removal Game
Problem: Given a string s, two players take turns removing a substring that satisfies some property (e.g., all characters same, palindrome, balanced, etc.). The player who cannot move loses. Determine the winner.
๐ Real-Time Thinking โ What Do I Know?
"This combines interval DP with game theory. Each move removes a contiguous substring, splitting the remaining string into left and right parts. The Grundy of a segment = mex of { Grundy(left) โ Grundy(right) | for each valid substring removal }."
๐ Edge Cases to Consider
No valid substring: Grundy = 0. First player loses.
Entire string is valid: First player removes entire string โ wins.
Only single-character removals: Game degrades to normal-play on n elements, which has Grundy = n mod 2.
All substrings valid: First player removes everything in one move โ wins.
Tip
โก Pattern Recognition: For any game where a move removes a contiguous segment and splits the board, the solution is always interval DP + Grundy (mex over XORs). This is the same pattern as Flip Game II, Kayles, Treblecross, and many others.
ProblemEmbed: even-number-addicts
ProblemEmbed: nullify-matrix
ProblemEmbed: substring-removal-game
๐ฏ Interview Cheat Sheet โ Advanced Strategy
Key Insight
Q1: When should I use the golden ratio for game theory? ONLY for Wythoff's Game (or its variants). The telltale signs: two piles, remove from one pile OR equal from both, and the expected solution is O(1). Golden ratio ฯ = (1+โ5)/2. Memorize it!
Key Insight
Q2: How do I know if a game decomposes via Sprague-Grundy? If a move splits the game into independent subgames (like flipping in Flip Game II breaks the string), the Grundy number of the whole = XOR of Grundy numbers of each subgame.
Key Insight
Q3: What's the difference between a palindrome subsequence vs substring? Subsequence can skip characters โ you can remove the ENTIRE string if it's all same characters.Substring must be contiguous โ requires interval DP. This distinction makes the Easy vs Hard versions completely different problems!
Key Insight
Q4: How do I handle game theory problems with multiple agents on a graph? Transform to a state space graph of (pos1, pos2, ..., turn). Use retrograde analysis(BFS from terminal states backward). Unresolved states = draw. This works for Cat & Mouse, World of Darkraft, and any multi-agent graph game with bounded state space.
Key Insight
Q5: When can I use simple parity/counting instead of DP? When the only thing that matters is even/odd counts or whether something exists. If the problem says "sum is even/odd" or "number of X determines the winner" โ look for a counting solution first. DP is often a trap on these problems!
Key Insight
Q6: What is a "cold position" / "P-position"? A position where the player about to move loses under optimal play. In Wythoff's Game, cold positions follow the Betty sequence: (โkยทฯโ, โkยทฯยฒโ). Memorize: cold = losing, hot = winning.
Key Insight
Q7: What's the strategy-stealing argument? In symmetric games, sometimes you can prove the first player wins by contradiction: if the second player had a winning strategy, the first player could "steal" it by making an irrelevant first move and then mirroring the opponent. This proves existence of a winning strategy without constructing it.
Key Insight
Q8: How do I handle "remove palindromic subsequence" problems? Easy: Single character type โ first player removes all in one move (always wins if non-empty).Hard: Two character types โ if the string is a palindrome, first player wins. If not, the second player can force a win by optimal play.
๐ Key Takeaways โ Advanced Strategy Games
Wythoff's Game uses the golden ratio ฯ = (1+โ5)/2 for Betty sequences: aโ = โkยทฯโ, bโ = aโ + k. Cold positions partition the naturals.
Flip Game II applies Sprague-Grundy to strings: flipping '++' splits the string into independent subgames. Grundy(n) = mex of XOR pairs from splits.
Palindrome Game Easy is trivial: single character type โ first player removes entire string at once. Always wins if non-empty.
Palindrome Game Hard with binary strings: palindrome โ first player wins. Not palindrome โ second player wins (using optimal counter-strategy).
Cat & Mouse transforms a graph game into a (mousePos, catPos, turn) state space with BFS backward induction. Three outcomes: mouse win, cat win, draw.
World of Darkraft extends state space to RPG stats. Use memoization on bounded state dimensions. Watch for exponential explosion!
Circle Game uses symmetry: strategy stealing or mirror strategies often determine the winner based on parity of n.
Even Number Addicts reduces to counting evens and odds. Only parity matters, not actual values.
Nullify Matrix is isomorphic to a bipartite graph game. Use Grundy numbers on row/column connections.
Substring Removal Game is interval DP + Grundy: dp[l][r] = mex{ dp[l][i-1] โ dp[j+1][r] for each valid substring [i,j] within [l,r] }.
Pattern
Technique
When to Use
Complexity
Betty Sequences
Golden ratio ฯ formula
Two-pile "remove from one or both equally"
O(1)
String Grundy
mex of XOR of split segments
Moves that split a string/array
O(nยฒ)
Palindrome Subsequence
Character counting / palindrome check
Remove palindromic subsequences
O(n)
State Space Graph
BFS backward induction on (posโ, posโ, turn)
Multi-agent graph games
O(Sยฒ)
Parity / Counting
Even/odd analysis
Sum-based or count-based win conditions
O(n)
Interval DP + Grundy
dp[l][r] = mex of XORs from removals
Remove substrings/subelements from a sequence
O(nยณ)
Note
๐ฎ What's Next? You've completed the entire game theory series! Review theDivisor & Elimination Gamesto reinforce the basics, or pick any problem from the list below to practice in the Playground.
๐ฎ All 10 Problems โ Master Them All!
Here's every problem covered in this article. Open each in the playground, implement the solution, and verify against the test cases. Start with the easier ones (Wythoff's, Flip Game II) and work up to the hard ones (Cat & Mouse, Nullify Matrix).
ProblemEmbed: wythoffs-game
ProblemEmbed: flip-game-ii
ProblemEmbed: palindrome-game-easy
ProblemEmbed: palindrome-game-hard
ProblemEmbed: cat-and-mouse
ProblemEmbed: world-of-darkraft
ProblemEmbed: circle-game
ProblemEmbed: even-number-addicts
ProblemEmbed: nullify-matrix
ProblemEmbed: substring-removal-game
function isWythoffCold(a, b) { // Ensure a <= b if (a > b) [a, b] = [b, a]; const phi = (1 + Math.sqrt(5)) / 2; const k = b - a; const ak = Math.floor(k * phi); return a === ak; // Cold if a matches Betty sequence}function solveWythoff(a, b) { if (isWythoffCold(a, b)) { return "First player loses (cold position)"; } return "First player wins (hot position)";}
function computeGrundy(maxN) { const grundy = new Array(maxN + 1).fill(0); for (let n = 2; n <= maxN; n++) { const reachable = new Set(); // Try flipping at each valid position for (let i = 0; i <= n - 2; i++) { const left = i; // length of left segment const right = n - i - 2; // length of right segment reachable.add(grundy[left] ^ grundy[right]); } // Find mex let g = 0; while (reachable.has(g)) g++; grundy[n] = g; } return grundy;}function canFlipGameWin(s) { const grundy = computeGrundy(s.length); // Split the string into contiguous '+' segments let xorSum = 0; let runLength = 0; for (const ch of s) { if (ch === '+') { runLength++; } else { xorSum ^= grundy[runLength]; runLength = 0; } } xorSum ^= grundy[runLength]; // Last segment return xorSum !== 0; // First player wins iff XOR โ 0}
function palindromeGameHard(s) { const n = s.length; // If palindrome, first player wins immediately if (isPalindrome(s)) return true; // For binary strings ('a'/'b'): Bob wins if not palindrome // But for full generality, use DP: const dp = Array.from({ length: n }, () => Array(n).fill(false)); // Base: single character is palindrome โ winning for (let i = 0; i < n; i++) dp[i][i] = true; // Interval DP for (let len = 2; len <= n; len++) { for (let l = 0; l + len <= n; l++) { const r = l + len - 1; // If entire substring is palindrome โ win if (isPalindromeRange(s, l, r)) { dp[l][r] = true; continue; } // Try removing each possible palindrome subsequence // (simplified: at least one move leads to opponent losing) dp[l][r] = canForceWin(s, l, r, dp); } } return dp[0][n - 1];}
function catMouseGame(graph) { const n = graph.length; const DRAW = 0, MOUSE_WIN = 1, CAT_WIN = 2; const MOUSE_TURN = 0, CAT_TURN = 1; // State: (mousePos, catPos, turn) // Initialize all as DRAW const result = Array.from({ length: n }, () => Array.from({ length: n }, () => [DRAW, DRAW])); // degree[m][c][turn] = number of outgoing moves from this state const degree = Array.from({ length: n }, () => Array.from({ length: n }, () => [0, 0])); // Calculate degrees for (let m = 0; m < n; m++) { for (let c = 0; c < n; c++) { degree[m][c][MOUSE_TURN] = graph[m].length; degree[m][c][CAT_TURN] = graph[c].length; } } const queue = []; // Terminal states for (let turn of [MOUSE_TURN, CAT_TURN]) { for (let i = 0; i < n; i++) { // Mouse at safe node 0 โ MOUSE WINS result[0][i][turn] = MOUSE_WIN; queue.push([0, i, turn]); // Cat catches mouse result[i][i][turn] = CAT_WIN; queue.push([i, i, turn]); } } // BFS propagation while (queue.length > 0) { const [m, c, turn] = queue.shift(); const curResult = result[m][c][turn]; // Predecessors: states that move into this state const prevTurn = 1 - turn; const prevPlayer = prevTurn === MOUSE_TURN ? m : c; for (const prev of graph[prevPlayer]) { const pm = prevTurn === MOUSE_TURN ? prev : m; const pc = prevTurn === CAT_TURN ? prev : c; if (result[pm][pc][prevTurn] !== DRAW) continue; if (prevTurn === MOUSE_TURN) { // Mouse's turn: if any move leads to MOUSE_WIN โ win if (curResult === MOUSE_WIN) { result[pm][pc][prevTurn] = MOUSE_WIN; queue.push([pm, pc, prevTurn]); } else { degree[pm][pc][prevTurn]--; if (degree[pm][pc][prevTurn] === 0) { result[pm][pc][prevTurn] = CAT_WIN; queue.push([pm, pc, prevTurn]); } } } else { // Cat's turn: symmetric if (curResult === CAT_WIN) { result[pm][pc][prevTurn] = CAT_WIN; queue.push([pm, pc, prevTurn]); } else { degree[pm][pc][prevTurn]--; if (degree[pm][pc][prevTurn] === 0) { result[pm][pc][prevTurn] = MOUSE_WIN; queue.push([pm, pc, prevTurn]); } } } } } return result[1][2][MOUSE_TURN];}
// Simplified state space DP for World of Darkraft// State: (hp1, hp2, turn) where hp is integer healthfunction darkraftGame(maxHP, actions) { const memo = new Map(); function canWin(hp1, hp2, isMyTurn) { if (hp2 <= 0) return true; // Opponent dead โ I win if (hp1 <= 0) return false; // I'm dead โ I lose const key = hp1 + "," + hp2 + "," + isMyTurn; if (memo.has(key)) return memo.get(key); if (isMyTurn) { // My turn: I can win if ANY action makes opponent lose for (const action of actions) { const dmg = computeDamage(action, hp1, hp2); if (canWin(hp1, hp2 - dmg, false)) { memo.set(key, true); return true; } } memo.set(key, false); return false; } else { // Opponent's turn: I can win only if ALL opponent's actions still let me win for (const action of actions) { const dmg = computeDamage(action, hp2, hp1); if (!canWin(hp1 - dmg, hp2, true)) { memo.set(key, false); return false; } } memo.set(key, true); return true; } } return canWin(initialHP1, initialHP2, true);}
function evenNumberAddicts(nums) { const evens = nums.filter(x => x % 2 === 0).length; const odds = nums.length - evens; // If no odd numbers โ all sums are even โ Alice wins if (odds === 0) return true; // Key parity analysis: const turns = Math.floor(odds / 2); const aliceTakesLastOdd = odds % 2 === 1; if (turns % 2 === 0) { // Even number of odd-pair turns return aliceTakesLastOdd || evens > 0; } else { // Odd number of odd-pair turns return aliceTakesLastOdd && evens > 0; }}
function nullifyMatrix(matrix) { const m = matrix.length; const n = matrix[0].length; // Count 1s per row and column const rowOnes = matrix.map(row => row.reduce((a, b) => a + b, 0)); const colOnes = Array(n).fill(0); for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) if (matrix[i][j]) colOnes[j]++; // If any row or column has all 1s, first player wins immediately // Otherwise, it's a Grundy-on-graph problem // The XOR of (row i has 1s) and (col j has 1s) doesn't directly give answer // Use Sprague-Grundy on the bipartite graph of rows/cols // Simplified: first player wins if there's at least one 1 const totalOnes = rowOnes.reduce((a, b) => a + b, 0); if (totalOnes === 0) return false; // No moves // More precise: use the Grundy number of the game state // which depends on the structure of remaining 1's return computeGrundyMatrix(matrix) !== 0;}
function substringRemovalGame(s, isValid) { const n = s.length; const grundy = Array(n + 1).fill(0); // Precompute which substrings are valid removals const valid = Array.from({ length: n }, () => Array(n).fill(false)); for (let l = 0; l < n; l++) { for (let r = l; r < n; r++) { valid[l][r] = isValid(s.substring(l, r + 1)); } } // Grundy[i] = Grundy number for prefix of length i // But actually we need interval Grundy for substring removal const dp = Array.from({ length: n }, () => Array(n).fill(0)); for (let len = 1; len <= n; len++) { for (let l = 0; l + len <= n; l++) { const r = l + len - 1; const reachable = new Set(); // Try removing each valid substring within [l, r] for (let i = l; i <= r; i++) { for (let j = i; j <= r; j++) { if (valid[i][j]) { const leftG = i > l ? dp[l][i - 1] : 0; const rightG = j < r ? dp[j + 1][r] : 0; reachable.add(leftG ^ rightG); } } } let g = 0; while (reachable.has(g)) g++; dp[l][r] = g; } } return dp[0][n - 1] !== 0; // First player wins if Grundy โ 0}