<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://myscratchpad.is-a.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin</id>
	<title>scratchpad - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://myscratchpad.is-a.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin"/>
	<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php/Special:Contributions/Admin"/>
	<updated>2026-09-14T20:52:13Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=390</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=390"/>
		<updated>2026-09-11T03:59:00Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{LOCALYEAR}}/{{LOCALMONTH}}/{{LOCALDAY2}}|action=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=378</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=378"/>
		<updated>2026-09-04T03:57:00Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{LOCALYEAR}}/{{LOCALMONTH}}/{{LOCALDAY2}}|veaction=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=376</id>
		<title>DSA/Chessboards and Queens</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=376"/>
		<updated>2026-09-03T04:51:52Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chessboard and Queens (CSES) — Backtracking Notes =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Problem:&#039;&#039;&#039; Place 8 queens on an 8×8 chessboard so that no two queens attack each other. Some squares are &#039;&#039;reserved&#039;&#039; (marked with a star in the input) and cannot hold a queen. Count the number of valid placements.&lt;br /&gt;
&lt;br /&gt;
== Why Is This a Recursion Problem? ==&lt;br /&gt;
&lt;br /&gt;
There are two strong signals that point to recursion (specifically &#039;&#039;&#039;backtracking&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;No natural iterative solution.&#039;&#039;&#039; We&#039;re placing 8 queens, and the number of valid choices for queen &#039;&#039;k&#039;&#039; depends entirely on how queens 1..k-1 were placed. You&#039;d need 8 nested for-loops, one per queen — and even that doesn&#039;t work cleanly, since the number of &#039;&#039;valid&#039;&#039; choices at each level changes dynamically.&lt;br /&gt;
# &#039;&#039;&#039;Tiny constraints.&#039;&#039;&#039; An 8×8 board is a dead giveaway. Constraints this small almost always mean the intended complexity is something like &amp;lt;code&amp;gt;O(2^n)&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;O(n!)&amp;lt;/code&amp;gt; — both are hallmarks of brute-force / backtracking search.&lt;br /&gt;
&lt;br /&gt;
== The Core Idea ==&lt;br /&gt;
&lt;br /&gt;
Since we need exactly one queen per row (8 queens, 8 rows), we can place them &#039;&#039;&#039;row by row&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* Write a recursive function &amp;lt;code&amp;gt;place(row)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* For the current row, try every column from 0 to 7.&lt;br /&gt;
* If the square is free (not reserved) and not attacked, place a queen there, recurse into &amp;lt;code&amp;gt;row + 1&amp;lt;/code&amp;gt;, then &#039;&#039;&#039;undo the placement&#039;&#039;&#039; (this is the &amp;quot;backtrack&amp;quot; step) before trying the next column.&lt;br /&gt;
* If &amp;lt;code&amp;gt;row == n&amp;lt;/code&amp;gt;, it means all 8 queens were placed successfully — increment the answer.&lt;br /&gt;
&lt;br /&gt;
The undo step is critical: after exploring one branch, the board must be restored to its previous state so the next column can be tried cleanly.&lt;br /&gt;
&lt;br /&gt;
== First Working Version: Brute-Force Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
The simplest (but slowest) way to check if a square is attacked is to literally scan:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Upward&#039;&#039;&#039; in the same column, for an existing queen.&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-left&#039;&#039;&#039; (decrementing both row and column).&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-right&#039;&#039;&#039; (decrementing row, incrementing column).&lt;br /&gt;
&lt;br /&gt;
This works, and on the actual 8×8 test case it&#039;s already fast (a couple of milliseconds), because the search space collapses quickly once conflicts are found. But it does unnecessary work — every single placement attempt re-scans the whole column and both diagonals.&lt;br /&gt;
&lt;br /&gt;
== Optimizing: O(1) Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
Instead of scanning every time, keep track of which columns and diagonals are &#039;&#039;&#039;already occupied&#039;&#039;&#039; using boolean arrays, updated incrementally as queens are placed and removed.&lt;br /&gt;
&lt;br /&gt;
=== Columns ===&lt;br /&gt;
&lt;br /&gt;
Trivial — one boolean array indexed by column:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(n, false);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Diagonals: The Grid Math Trick ===&lt;br /&gt;
&lt;br /&gt;
This is the part worth internalizing, since it comes up in many other grid problems.&lt;br /&gt;
&lt;br /&gt;
There are two diagonal directions on a grid, and each has a simple invariant:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 1 (↘ direction, i.e. going down-right / cells where row and column both increase together):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Take a 4×4 board and look at the diagonal containing (0,3), (1,2), (2,1), (3,0). Notice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;row + col = 3 \quad \text{for every cell on this diagonal}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next diagonal over — (1,3), (2,2), (3,1) — satisfies &amp;lt;math&amp;gt;row + col = 4&amp;lt;/math&amp;gt;. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↘&amp;quot;-type diagonal if and only if &amp;lt;math&amp;gt;row + col&amp;lt;/math&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This matches the geometric fact that a line of the form &amp;lt;math&amp;gt;y + x = c&amp;lt;/math&amp;gt; is a straight line tilted at 45°.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 2 (↙ direction):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Look at (1,0), (2,1), (3,2): here &amp;lt;math&amp;gt;row - col = 1&amp;lt;/math&amp;gt; for all of them. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↙&amp;quot;-type diagonal if and only if &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The negative-index problem:&#039;&#039;&#039; &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; can be negative (e.g. row=0, col=7 gives −7), and arrays can&#039;t have negative indices. The fix is a constant offset: since the minimum possible value of &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is &amp;lt;math&amp;gt;-(n-1)&amp;lt;/math&amp;gt;, add &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; to shift everything into the non-negative range:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;index = row - col + (n - 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both diagonal arrays need size &amp;lt;math&amp;gt;2n - 1&amp;lt;/math&amp;gt; (for n=8, that&#039;s 15 — matching the fact that an 8×8 board really does have 15 diagonals in each direction).&lt;br /&gt;
&lt;br /&gt;
== Final Code ==&lt;br /&gt;
&lt;br /&gt;
Same algorithm, three languages. The logic is identical in all three: row-by-row backtracking with O(1) column/diagonal checks via boolean arrays.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
|-|C++=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
int n = 8;&lt;br /&gt;
vector&amp;lt;string&amp;gt; grid;&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(8, false);&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag1Attacked(15, false); // indexed by row + col&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag2Attacked(15, false); // indexed by row - col + (n - 1)&lt;br /&gt;
&lt;br /&gt;
long long answer = 0;&lt;br /&gt;
&lt;br /&gt;
void place(int row) {&lt;br /&gt;
    if (row == n) {&lt;br /&gt;
        answer++;&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    for (int col = 0; col &amp;lt; n; col++) {&lt;br /&gt;
        if (grid[row][col] == &#039;*&#039;) continue;               // reserved square&lt;br /&gt;
        if (colAttacked[col]) continue;&lt;br /&gt;
        if (diag1Attacked[row + col]) continue;&lt;br /&gt;
        if (diag2Attacked[row - col + n - 1]) continue;&lt;br /&gt;
&lt;br /&gt;
        // place queen&lt;br /&gt;
        colAttacked[col] = true;&lt;br /&gt;
        diag1Attacked[row + col] = true;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = true;&lt;br /&gt;
&lt;br /&gt;
        place(row + 1);&lt;br /&gt;
&lt;br /&gt;
        // backtrack: undo placement&lt;br /&gt;
        colAttacked[col] = false;&lt;br /&gt;
        diag1Attacked[row + col] = false;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    grid.resize(n);&lt;br /&gt;
    for (auto &amp;amp;row : grid) cin &amp;gt;&amp;gt; row;&lt;br /&gt;
&lt;br /&gt;
    place(0);&lt;br /&gt;
    cout &amp;lt;&amp;lt; answer &amp;lt;&amp;lt; endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def place(row):&lt;br /&gt;
    global answer&lt;br /&gt;
    if row == n:&lt;br /&gt;
        answer += 1&lt;br /&gt;
        return&lt;br /&gt;
    for col in range(n):&lt;br /&gt;
        if grid[row][col] == &#039;*&#039;:&lt;br /&gt;
            continue&lt;br /&gt;
        if col_attacked[col]:&lt;br /&gt;
            continue&lt;br /&gt;
        if diag1_attacked[row + col]:&lt;br /&gt;
            continue&lt;br /&gt;
        if diag2_attacked[row - col + n - 1]:&lt;br /&gt;
            continue&lt;br /&gt;
&lt;br /&gt;
        col_attacked[col] = True&lt;br /&gt;
        diag1_attacked[row + col] = True&lt;br /&gt;
        diag2_attacked[row - col + n - 1] = True&lt;br /&gt;
&lt;br /&gt;
        place(row + 1)&lt;br /&gt;
&lt;br /&gt;
        col_attacked[col] = False&lt;br /&gt;
        diag1_attacked[row + col] = False&lt;br /&gt;
        diag2_attacked[row - col + n - 1] = False&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    global n, grid, col_attacked, diag1_attacked, diag2_attacked, answer&lt;br /&gt;
    n = 8&lt;br /&gt;
    grid = [input() for _ in range(n)]&lt;br /&gt;
    col_attacked = [False] * n&lt;br /&gt;
    diag1_attacked = [False] * (2 * n - 1)&lt;br /&gt;
    diag2_attacked = [False] * (2 * n - 1)&lt;br /&gt;
    answer = 0&lt;br /&gt;
&lt;br /&gt;
    sys.setrecursionlimit(10000)&lt;br /&gt;
    place(0)&lt;br /&gt;
    print(answer)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|Rust=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
use std::io::{self, Read};&lt;br /&gt;
&lt;br /&gt;
const N: usize = 8;&lt;br /&gt;
&lt;br /&gt;
struct Solver {&lt;br /&gt;
    grid: Vec&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;,&lt;br /&gt;
    col_attacked: [bool; N],&lt;br /&gt;
    diag1_attacked: [bool; 2 * N - 1], // indexed by row + col&lt;br /&gt;
    diag2_attacked: [bool; 2 * N - 1], // indexed by row + (N - 1) - col&lt;br /&gt;
    answer: u64,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
impl Solver {&lt;br /&gt;
    fn place(&amp;amp;mut self, row: usize) {&lt;br /&gt;
        if row == N {&lt;br /&gt;
            self.answer += 1;&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        for col in 0..N {&lt;br /&gt;
            if self.grid[row][col] == b&#039;*&#039; {&lt;br /&gt;
                continue; // reserved square&lt;br /&gt;
            }&lt;br /&gt;
            if self.col_attacked[col] {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
            let d1 = row + col;&lt;br /&gt;
            let d2 = row + N - 1 - col; // usize-safe version of row - col + (N - 1)&lt;br /&gt;
            if self.diag1_attacked[d1] || self.diag2_attacked[d2] {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            self.col_attacked[col] = true;&lt;br /&gt;
            self.diag1_attacked[d1] = true;&lt;br /&gt;
            self.diag2_attacked[d2] = true;&lt;br /&gt;
&lt;br /&gt;
            self.place(row + 1);&lt;br /&gt;
&lt;br /&gt;
            // backtrack: undo placement&lt;br /&gt;
            self.col_attacked[col] = false;&lt;br /&gt;
            self.diag1_attacked[d1] = false;&lt;br /&gt;
            self.diag2_attacked[d2] = false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fn main() {&lt;br /&gt;
    let mut input = String::new();&lt;br /&gt;
    io::stdin().read_to_string(&amp;amp;mut input).unwrap();&lt;br /&gt;
    let grid: Vec&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt; = input&lt;br /&gt;
        .lines()&lt;br /&gt;
        .take(N)&lt;br /&gt;
        .map(|line| line.as_bytes().to_vec())&lt;br /&gt;
        .collect();&lt;br /&gt;
&lt;br /&gt;
    let mut solver = Solver {&lt;br /&gt;
        grid,&lt;br /&gt;
        col_attacked: [false; N],&lt;br /&gt;
        diag1_attacked: [false; 2 * N - 1],&lt;br /&gt;
        diag2_attacked: [false; 2 * N - 1],&lt;br /&gt;
        answer: 0,&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    solver.place(0);&lt;br /&gt;
    println!(&amp;quot;{}&amp;quot;, solver.answer);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it&#039;s &#039;&#039;&#039;not necessary&#039;&#039;&#039; to actually mark the square in &amp;lt;code&amp;gt;grid&amp;lt;/code&amp;gt; as a queen (&#039;Q&#039;); the three boolean arrays already fully capture every constraint we need to check, so there&#039;s nothing to gain from also mutating the grid string. The Rust version sidesteps the negative-index offset by rewriting &amp;lt;math&amp;gt;row - col + (n-1)&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;row + (n-1) - col&amp;lt;/math&amp;gt;, which is equivalent but never underflows a &amp;lt;code&amp;gt;usize&amp;lt;/code&amp;gt; mid-expression.&lt;br /&gt;
&lt;br /&gt;
== Complexity ==&lt;br /&gt;
&lt;br /&gt;
* Row 0 has at most 8 choices, row 1 has at most 7 (one column already taken), and so on — giving a rough bound of &#039;&#039;&#039;O(n!)&#039;&#039;&#039;, possibly with an extra factor of n from the per-row scan: &#039;&#039;&#039;O(n! · n)&#039;&#039;&#039;.&lt;br /&gt;
* In practice it&#039;s &#039;&#039;&#039;much faster&#039;&#039;&#039; than this bound suggests, because diagonal constraints prune the search tree aggressively. On the empty 8×8 board (the worst case, since nothing is reserved), the recursion has exactly &#039;&#039;&#039;92 leaves&#039;&#039;&#039; (the well-known number of solutions to the 8-queens problem) and runs in about a millisecond.&lt;br /&gt;
* This approach does &#039;&#039;&#039;not&#039;&#039;&#039; scale to large n (e.g. n = 1000). Placing n non-attacking queens under arbitrary reserved-square constraints is a much harder problem in general — for large boards you need entirely different techniques (or the instance may simply be intractable).&lt;br /&gt;
&lt;br /&gt;
== What Is Backtracking? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Backtracking&#039;&#039;&#039; is the name for exactly this pattern: recursively try a choice, recurse further assuming that choice, and if a later step hits a dead end (no valid moves possible), &#039;&#039;&#039;undo the choice&#039;&#039;&#039; (&amp;quot;backtrack&amp;quot;) and try the next alternative. The name comes from the fact that the recursion tree doesn&#039;t just go forward — it routinely retreats and retries.&lt;br /&gt;
&lt;br /&gt;
Some useful mental models:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s the same technique behind &#039;&#039;&#039;Sudoku solvers&#039;&#039;&#039;: try a digit, recurse, and if a contradiction is eventually reached, undo and try a different digit.&lt;br /&gt;
* Backtracking is typically used to find &#039;&#039;&#039;one valid solution&#039;&#039;&#039; (Sudoku) or to &#039;&#039;&#039;count all valid solutions&#039;&#039;&#039; (this problem) when there&#039;s no faster closed-form or DP approach — often because the problem is NP-hard in general.&lt;br /&gt;
* Backtracking problems are almost always about a &amp;quot;good enough&amp;quot; solution rather than a provably optimal one. There is nearly always room to add smarter pruning:&lt;br /&gt;
** Example: if you can detect &#039;&#039;before&#039;&#039; recursing that some later row has only one legal column left, you can propagate that constraint early and cut off huge unproductive branches. This kind of look-ahead pruning can make backtracking &#039;&#039;&#039;hundreds or even thousands of times faster&#039;&#039;&#039; — but it&#039;s an enhancement on top of the base algorithm, not a change to its fundamental structure.&lt;br /&gt;
&lt;br /&gt;
== Key Takeaways ==&lt;br /&gt;
&lt;br /&gt;
* Small constraints (like n = 8) are a strong hint that the intended solution is exponential/factorial-time backtracking.&lt;br /&gt;
* Always pair &amp;quot;make a move&amp;quot; with &amp;quot;undo the move&amp;quot; (backtrack) after the recursive call returns — this is what makes the search correct.&lt;br /&gt;
* For diagonal checks on a grid, remember:&lt;br /&gt;
** &amp;lt;math&amp;gt;row + col&amp;lt;/math&amp;gt; is constant along one diagonal direction.&lt;br /&gt;
** &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is constant along the other (add an offset of &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; to keep indices non-negative).&lt;br /&gt;
* Prefer O(1) incremental state (boolean arrays) over re-scanning the board on every check — it turns an already-fast solution into a very fast one.&lt;br /&gt;
* Global arrays/variables are common in competitive programming for exactly this kind of state — avoids passing/copying containers on every recursive call.&lt;br /&gt;
&lt;br /&gt;
[[Category:DSA]]&lt;br /&gt;
[[Category:Backtracking]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=MediaWiki:Tabberneue-tabbertransclude-category&amp;diff=375</id>
		<title>MediaWiki:Tabberneue-tabbertransclude-category</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=MediaWiki:Tabberneue-tabbertransclude-category&amp;diff=375"/>
		<updated>2026-09-03T04:49:55Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created blank page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=MediaWiki:Tabberneue-tabber-category&amp;diff=374</id>
		<title>MediaWiki:Tabberneue-tabber-category</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=MediaWiki:Tabberneue-tabber-category&amp;diff=374"/>
		<updated>2026-09-03T04:49:46Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created blank page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=373</id>
		<title>DSA/Chessboards and Queens</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=373"/>
		<updated>2026-09-03T04:41:34Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chessboard and Queens (CSES) — Backtracking Notes =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Problem:&#039;&#039;&#039; Place 8 queens on an 8×8 chessboard so that no two queens attack each other. Some squares are &#039;&#039;reserved&#039;&#039; (marked with a star in the input) and cannot hold a queen. Count the number of valid placements.&lt;br /&gt;
&lt;br /&gt;
== Why Is This a Recursion Problem? ==&lt;br /&gt;
&lt;br /&gt;
There are two strong signals that point to recursion (specifically &#039;&#039;&#039;backtracking&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;No natural iterative solution.&#039;&#039;&#039; We&#039;re placing 8 queens, and the number of valid choices for queen &#039;&#039;k&#039;&#039; depends entirely on how queens 1..k-1 were placed. You&#039;d need 8 nested for-loops, one per queen — and even that doesn&#039;t work cleanly, since the number of &#039;&#039;valid&#039;&#039; choices at each level changes dynamically.&lt;br /&gt;
# &#039;&#039;&#039;Tiny constraints.&#039;&#039;&#039; An 8×8 board is a dead giveaway. Constraints this small almost always mean the intended complexity is something like &amp;lt;code&amp;gt;O(2^n)&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;O(n!)&amp;lt;/code&amp;gt; — both are hallmarks of brute-force / backtracking search.&lt;br /&gt;
&lt;br /&gt;
== The Core Idea ==&lt;br /&gt;
&lt;br /&gt;
Since we need exactly one queen per row (8 queens, 8 rows), we can place them &#039;&#039;&#039;row by row&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* Write a recursive function &amp;lt;code&amp;gt;place(row)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* For the current row, try every column from 0 to 7.&lt;br /&gt;
* If the square is free (not reserved) and not attacked, place a queen there, recurse into &amp;lt;code&amp;gt;row + 1&amp;lt;/code&amp;gt;, then &#039;&#039;&#039;undo the placement&#039;&#039;&#039; (this is the &amp;quot;backtrack&amp;quot; step) before trying the next column.&lt;br /&gt;
* If &amp;lt;code&amp;gt;row == n&amp;lt;/code&amp;gt;, it means all 8 queens were placed successfully — increment the answer.&lt;br /&gt;
&lt;br /&gt;
The undo step is critical: after exploring one branch, the board must be restored to its previous state so the next column can be tried cleanly.&lt;br /&gt;
&lt;br /&gt;
== First Working Version: Brute-Force Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
The simplest (but slowest) way to check if a square is attacked is to literally scan:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Upward&#039;&#039;&#039; in the same column, for an existing queen.&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-left&#039;&#039;&#039; (decrementing both row and column).&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-right&#039;&#039;&#039; (decrementing row, incrementing column).&lt;br /&gt;
&lt;br /&gt;
This works, and on the actual 8×8 test case it&#039;s already fast (a couple of milliseconds), because the search space collapses quickly once conflicts are found. But it does unnecessary work — every single placement attempt re-scans the whole column and both diagonals.&lt;br /&gt;
&lt;br /&gt;
== Optimizing: O(1) Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
Instead of scanning every time, keep track of which columns and diagonals are &#039;&#039;&#039;already occupied&#039;&#039;&#039; using boolean arrays, updated incrementally as queens are placed and removed.&lt;br /&gt;
&lt;br /&gt;
=== Columns ===&lt;br /&gt;
&lt;br /&gt;
Trivial — one boolean array indexed by column:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(n, false);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Diagonals: The Grid Math Trick ===&lt;br /&gt;
&lt;br /&gt;
This is the part worth internalizing, since it comes up in many other grid problems.&lt;br /&gt;
&lt;br /&gt;
There are two diagonal directions on a grid, and each has a simple invariant:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 1 (↘ direction, i.e. going down-right / cells where row and column both increase together):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Take a 4×4 board and look at the diagonal containing (0,3), (1,2), (2,1), (3,0). Notice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;row + col = 3 \quad \text{for every cell on this diagonal}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next diagonal over — (1,3), (2,2), (3,1) — satisfies &amp;lt;math&amp;gt;row + col = 4&amp;lt;/math&amp;gt;. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↘&amp;quot;-type diagonal if and only if &amp;lt;math&amp;gt;row + col&amp;lt;/math&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This matches the geometric fact that a line of the form &amp;lt;math&amp;gt;y + x = c&amp;lt;/math&amp;gt; is a straight line tilted at 45°.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 2 (↙ direction):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Look at (1,0), (2,1), (3,2): here &amp;lt;math&amp;gt;row - col = 1&amp;lt;/math&amp;gt; for all of them. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↙&amp;quot;-type diagonal if and only if &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The negative-index problem:&#039;&#039;&#039; &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; can be negative (e.g. row=0, col=7 gives −7), and arrays can&#039;t have negative indices. The fix is a constant offset: since the minimum possible value of &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is &amp;lt;math&amp;gt;-(n-1)&amp;lt;/math&amp;gt;, add &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; to shift everything into the non-negative range:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;index = row - col + (n - 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both diagonal arrays need size &amp;lt;math&amp;gt;2n - 1&amp;lt;/math&amp;gt; (for n=8, that&#039;s 15 — matching the fact that an 8×8 board really does have 15 diagonals in each direction).&lt;br /&gt;
&lt;br /&gt;
== Final Code ==&lt;br /&gt;
&lt;br /&gt;
Same algorithm, three languages. The logic is identical in all three: row-by-row backtracking with O(1) column/diagonal checks via boolean arrays.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
|-|C++=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
int n = 8;&lt;br /&gt;
vector&amp;lt;string&amp;gt; grid;&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(8, false);&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag1Attacked(15, false); // indexed by row + col&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag2Attacked(15, false); // indexed by row - col + (n - 1)&lt;br /&gt;
&lt;br /&gt;
long long answer = 0;&lt;br /&gt;
&lt;br /&gt;
void place(int row) {&lt;br /&gt;
    if (row == n) {&lt;br /&gt;
        answer++;&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    for (int col = 0; col &amp;lt; n; col++) {&lt;br /&gt;
        if (grid[row][col] == &#039;*&#039;) continue;               // reserved square&lt;br /&gt;
        if (colAttacked[col]) continue;&lt;br /&gt;
        if (diag1Attacked[row + col]) continue;&lt;br /&gt;
        if (diag2Attacked[row - col + n - 1]) continue;&lt;br /&gt;
&lt;br /&gt;
        // place queen&lt;br /&gt;
        colAttacked[col] = true;&lt;br /&gt;
        diag1Attacked[row + col] = true;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = true;&lt;br /&gt;
&lt;br /&gt;
        place(row + 1);&lt;br /&gt;
&lt;br /&gt;
        // backtrack: undo placement&lt;br /&gt;
        colAttacked[col] = false;&lt;br /&gt;
        diag1Attacked[row + col] = false;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    grid.resize(n);&lt;br /&gt;
    for (auto &amp;amp;row : grid) cin &amp;gt;&amp;gt; row;&lt;br /&gt;
&lt;br /&gt;
    place(0);&lt;br /&gt;
    cout &amp;lt;&amp;lt; answer &amp;lt;&amp;lt; endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def place(row):&lt;br /&gt;
    global answer&lt;br /&gt;
    if row == n:&lt;br /&gt;
        answer += 1&lt;br /&gt;
        return&lt;br /&gt;
    for col in range(n):&lt;br /&gt;
        if grid[row][col] == &#039;*&#039;:&lt;br /&gt;
            continue&lt;br /&gt;
        if col_attacked[col]:&lt;br /&gt;
            continue&lt;br /&gt;
        if diag1_attacked[row + col]:&lt;br /&gt;
            continue&lt;br /&gt;
        if diag2_attacked[row - col + n - 1]:&lt;br /&gt;
            continue&lt;br /&gt;
&lt;br /&gt;
        col_attacked[col] = True&lt;br /&gt;
        diag1_attacked[row + col] = True&lt;br /&gt;
        diag2_attacked[row - col + n - 1] = True&lt;br /&gt;
&lt;br /&gt;
        place(row + 1)&lt;br /&gt;
&lt;br /&gt;
        col_attacked[col] = False&lt;br /&gt;
        diag1_attacked[row + col] = False&lt;br /&gt;
        diag2_attacked[row - col + n - 1] = False&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    global n, grid, col_attacked, diag1_attacked, diag2_attacked, answer&lt;br /&gt;
    n = 8&lt;br /&gt;
    grid = [input() for _ in range(n)]&lt;br /&gt;
    col_attacked = [False] * n&lt;br /&gt;
    diag1_attacked = [False] * (2 * n - 1)&lt;br /&gt;
    diag2_attacked = [False] * (2 * n - 1)&lt;br /&gt;
    answer = 0&lt;br /&gt;
&lt;br /&gt;
    sys.setrecursionlimit(10000)&lt;br /&gt;
    place(0)&lt;br /&gt;
    print(answer)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|Rust=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
use std::io::{self, Read};&lt;br /&gt;
&lt;br /&gt;
const N: usize = 8;&lt;br /&gt;
&lt;br /&gt;
struct Solver {&lt;br /&gt;
    grid: Vec&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;,&lt;br /&gt;
    col_attacked: [bool; N],&lt;br /&gt;
    diag1_attacked: [bool; 2 * N - 1], // indexed by row + col&lt;br /&gt;
    diag2_attacked: [bool; 2 * N - 1], // indexed by row + (N - 1) - col&lt;br /&gt;
    answer: u64,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
impl Solver {&lt;br /&gt;
    fn place(&amp;amp;mut self, row: usize) {&lt;br /&gt;
        if row == N {&lt;br /&gt;
            self.answer += 1;&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        for col in 0..N {&lt;br /&gt;
            if self.grid[row][col] == b&#039;*&#039; {&lt;br /&gt;
                continue; // reserved square&lt;br /&gt;
            }&lt;br /&gt;
            if self.col_attacked[col] {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
            let d1 = row + col;&lt;br /&gt;
            let d2 = row + N - 1 - col; // usize-safe version of row - col + (N - 1)&lt;br /&gt;
            if self.diag1_attacked[d1] || self.diag2_attacked[d2] {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            self.col_attacked[col] = true;&lt;br /&gt;
            self.diag1_attacked[d1] = true;&lt;br /&gt;
            self.diag2_attacked[d2] = true;&lt;br /&gt;
&lt;br /&gt;
            self.place(row + 1);&lt;br /&gt;
&lt;br /&gt;
            // backtrack: undo placement&lt;br /&gt;
            self.col_attacked[col] = false;&lt;br /&gt;
            self.diag1_attacked[d1] = false;&lt;br /&gt;
            self.diag2_attacked[d2] = false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fn main() {&lt;br /&gt;
    let mut input = String::new();&lt;br /&gt;
    io::stdin().read_to_string(&amp;amp;mut input).unwrap();&lt;br /&gt;
    let grid: Vec&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt; = input&lt;br /&gt;
        .lines()&lt;br /&gt;
        .take(N)&lt;br /&gt;
        .map(|line| line.as_bytes().to_vec())&lt;br /&gt;
        .collect();&lt;br /&gt;
&lt;br /&gt;
    let mut solver = Solver {&lt;br /&gt;
        grid,&lt;br /&gt;
        col_attacked: [false; N],&lt;br /&gt;
        diag1_attacked: [false; 2 * N - 1],&lt;br /&gt;
        diag2_attacked: [false; 2 * N - 1],&lt;br /&gt;
        answer: 0,&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    solver.place(0);&lt;br /&gt;
    println!(&amp;quot;{}&amp;quot;, solver.answer);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it&#039;s &#039;&#039;&#039;not necessary&#039;&#039;&#039; to actually mark the square in &amp;lt;code&amp;gt;grid&amp;lt;/code&amp;gt; as a queen (&#039;Q&#039;); the three boolean arrays already fully capture every constraint we need to check, so there&#039;s nothing to gain from also mutating the grid string. The Rust version sidesteps the negative-index offset by rewriting &amp;lt;math&amp;gt;row - col + (n-1)&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;row + (n-1) - col&amp;lt;/math&amp;gt;, which is equivalent but never underflows a &amp;lt;code&amp;gt;usize&amp;lt;/code&amp;gt; mid-expression.&lt;br /&gt;
&lt;br /&gt;
== Complexity ==&lt;br /&gt;
&lt;br /&gt;
* Row 0 has at most 8 choices, row 1 has at most 7 (one column already taken), and so on — giving a rough bound of &#039;&#039;&#039;O(n!)&#039;&#039;&#039;, possibly with an extra factor of n from the per-row scan: &#039;&#039;&#039;O(n! · n)&#039;&#039;&#039;.&lt;br /&gt;
* In practice it&#039;s &#039;&#039;&#039;much faster&#039;&#039;&#039; than this bound suggests, because diagonal constraints prune the search tree aggressively. On the empty 8×8 board (the worst case, since nothing is reserved), the recursion has exactly &#039;&#039;&#039;92 leaves&#039;&#039;&#039; (the well-known number of solutions to the 8-queens problem) and runs in about a millisecond.&lt;br /&gt;
* This approach does &#039;&#039;&#039;not&#039;&#039;&#039; scale to large n (e.g. n = 1000). Placing n non-attacking queens under arbitrary reserved-square constraints is a much harder problem in general — for large boards you need entirely different techniques (or the instance may simply be intractable).&lt;br /&gt;
&lt;br /&gt;
== What Is Backtracking? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Backtracking&#039;&#039;&#039; is the name for exactly this pattern: recursively try a choice, recurse further assuming that choice, and if a later step hits a dead end (no valid moves possible), &#039;&#039;&#039;undo the choice&#039;&#039;&#039; (&amp;quot;backtrack&amp;quot;) and try the next alternative. The name comes from the fact that the recursion tree doesn&#039;t just go forward — it routinely retreats and retries.&lt;br /&gt;
&lt;br /&gt;
Some useful mental models:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s the same technique behind &#039;&#039;&#039;Sudoku solvers&#039;&#039;&#039;: try a digit, recurse, and if a contradiction is eventually reached, undo and try a different digit.&lt;br /&gt;
* Backtracking is typically used to find &#039;&#039;&#039;one valid solution&#039;&#039;&#039; (Sudoku) or to &#039;&#039;&#039;count all valid solutions&#039;&#039;&#039; (this problem) when there&#039;s no faster closed-form or DP approach — often because the problem is NP-hard in general.&lt;br /&gt;
* Backtracking problems are almost always about a &amp;quot;good enough&amp;quot; solution rather than a provably optimal one. There is nearly always room to add smarter pruning:&lt;br /&gt;
** Example: if you can detect &#039;&#039;before&#039;&#039; recursing that some later row has only one legal column left, you can propagate that constraint early and cut off huge unproductive branches. This kind of look-ahead pruning can make backtracking &#039;&#039;&#039;hundreds or even thousands of times faster&#039;&#039;&#039; — but it&#039;s an enhancement on top of the base algorithm, not a change to its fundamental structure.&lt;br /&gt;
&lt;br /&gt;
== Key Takeaways ==&lt;br /&gt;
&lt;br /&gt;
* Small constraints (like n = 8) are a strong hint that the intended solution is exponential/factorial-time backtracking.&lt;br /&gt;
* Always pair &amp;quot;make a move&amp;quot; with &amp;quot;undo the move&amp;quot; (backtrack) after the recursive call returns — this is what makes the search correct.&lt;br /&gt;
* For diagonal checks on a grid, remember:&lt;br /&gt;
** &amp;lt;math&amp;gt;row + col&amp;lt;/math&amp;gt; is constant along one diagonal direction.&lt;br /&gt;
** &amp;lt;math&amp;gt;row - col&amp;lt;/math&amp;gt; is constant along the other (add an offset of &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; to keep indices non-negative).&lt;br /&gt;
* Prefer O(1) incremental state (boolean arrays) over re-scanning the board on every check — it turns an already-fast solution into a very fast one.&lt;br /&gt;
* Global arrays/variables are common in competitive programming for exactly this kind of state — avoids passing/copying containers on every recursive call.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=372</id>
		<title>DSA/Chessboards and Queens</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=DSA/Chessboards_and_Queens&amp;diff=372"/>
		<updated>2026-09-03T04:38:17Z</updated>

		<summary type="html">&lt;p&gt;Admin: Create Chessboard &amp;amp; Queens problem solution&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chessboard and Queens (CSES) =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Problem:&#039;&#039;&#039; Place 8 queens on an 8×8 chessboard so that no two queens attack each other. Some squares are &#039;&#039;reserved&#039;&#039; (marked with a star in the input) and cannot hold a queen. Count the number of valid placements.&lt;br /&gt;
&lt;br /&gt;
== Why Is This a Recursion Problem? ==&lt;br /&gt;
&lt;br /&gt;
There are two strong signals that point to recursion (specifically &#039;&#039;&#039;backtracking&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;No natural iterative solution.&#039;&#039;&#039; We&#039;re placing 8 queens, and the number of valid choices for queen &#039;&#039;k&#039;&#039; depends entirely on how queens 1..k-1 were placed. You&#039;d need 8 nested for-loops, one per queen — and even that doesn&#039;t work cleanly, since the number of &#039;&#039;valid&#039;&#039; choices at each level changes dynamically.&lt;br /&gt;
# &#039;&#039;&#039;Tiny constraints.&#039;&#039;&#039; An 8×8 board is a dead giveaway. Constraints this small almost always mean the intended complexity is something like &amp;lt;code&amp;gt;O(2^n)&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;O(n!)&amp;lt;/code&amp;gt; — both are hallmarks of brute-force / backtracking search.&lt;br /&gt;
&lt;br /&gt;
== The Core Idea ==&lt;br /&gt;
&lt;br /&gt;
Since we need exactly one queen per row (8 queens, 8 rows), we can place them &#039;&#039;&#039;row by row&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* Write a recursive function &amp;lt;code&amp;gt;place(row)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* For the current row, try every column from 0 to 7.&lt;br /&gt;
* If the square is free (not reserved) and not attacked, place a queen there, recurse into &amp;lt;code&amp;gt;row + 1&amp;lt;/code&amp;gt;, then &#039;&#039;&#039;undo the placement&#039;&#039;&#039; (this is the &amp;quot;backtrack&amp;quot; step) before trying the next column.&lt;br /&gt;
* If &amp;lt;code&amp;gt;row == n&amp;lt;/code&amp;gt;, it means all 8 queens were placed successfully — increment the answer.&lt;br /&gt;
&lt;br /&gt;
The undo step is critical: after exploring one branch, the board must be restored to its previous state so the next column can be tried cleanly.&lt;br /&gt;
&lt;br /&gt;
== First Working Version: Brute-Force Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
The simplest (but slowest) way to check if a square is attacked is to literally scan:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Upward&#039;&#039;&#039; in the same column, for an existing queen.&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-left&#039;&#039;&#039; (decrementing both row and column).&lt;br /&gt;
* &#039;&#039;&#039;Diagonally up-right&#039;&#039;&#039; (decrementing row, incrementing column).&lt;br /&gt;
&lt;br /&gt;
This works, and on the actual 8×8 test case it&#039;s already fast (a couple of milliseconds), because the search space collapses quickly once conflicts are found. But it does unnecessary work — every single placement attempt re-scans the whole column and both diagonals.&lt;br /&gt;
&lt;br /&gt;
== Optimizing: O(1) Attack Checks ==&lt;br /&gt;
&lt;br /&gt;
Instead of scanning every time, keep track of which columns and diagonals are &#039;&#039;&#039;already occupied&#039;&#039;&#039; using boolean arrays, updated incrementally as queens are placed and removed.&lt;br /&gt;
&lt;br /&gt;
=== Columns ===&lt;br /&gt;
&lt;br /&gt;
Trivial — one boolean array indexed by column:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(n, false);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Diagonals: The Grid Math Trick ===&lt;br /&gt;
&lt;br /&gt;
This is the part worth internalizing, since it comes up in many other grid problems.&lt;br /&gt;
&lt;br /&gt;
There are two diagonal directions on a grid, and each has a simple invariant:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 1 (↘ direction, i.e. going down-right / cells where row and column both increase together):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Take a 4×4 board and look at the diagonal containing (0,3), (1,2), (2,1), (3,0). Notice:&lt;br /&gt;
&lt;br /&gt;
 row + col = 3   &#039;&#039;&#039;for every cell on this diagonal&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The next diagonal over — (1,3), (2,2), (3,1) — satisfies &amp;lt;code&amp;gt;row + col = 4&amp;lt;/code&amp;gt;. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↘&amp;quot;-type diagonal if and only if &amp;lt;code&amp;gt;row + col&amp;lt;/code&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This matches the geometric fact that a line of the form &amp;lt;code&amp;gt;y + x = constant&amp;lt;/code&amp;gt; is a straight line tilted at 45°.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagonal type 2 (↙ direction):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Look at (1,0), (2,1), (3,2): here &amp;lt;code&amp;gt;row − col = 1&amp;lt;/code&amp;gt; for all of them. In general:&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Two cells lie on the same &amp;quot;↙&amp;quot;-type diagonal if and only if &amp;lt;code&amp;gt;row − col&amp;lt;/code&amp;gt; is the same for both.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The negative-index problem:&#039;&#039;&#039; &amp;lt;code&amp;gt;row − col&amp;lt;/code&amp;gt; can be negative (e.g. row=0, col=7 gives −7), and arrays can&#039;t have negative indices. The fix is a constant offset: since the minimum possible value of &amp;lt;code&amp;gt;row − col&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;−(n−1)&amp;lt;/code&amp;gt;, add &amp;lt;code&amp;gt;n − 1&amp;lt;/code&amp;gt; to shift everything into the non-negative range:&lt;br /&gt;
&lt;br /&gt;
 index = row - col + (n - 1)&lt;br /&gt;
&lt;br /&gt;
Both diagonal arrays need size &amp;lt;code&amp;gt;2n − 1&amp;lt;/code&amp;gt; (for n=8, that&#039;s 15 — matching the fact that an 8×8 board really does have 15 diagonals in each direction).&lt;br /&gt;
&lt;br /&gt;
== Final Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
int n = 8;&lt;br /&gt;
vector&amp;lt;string&amp;gt; grid;&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;bool&amp;gt; colAttacked(8, false);&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag1Attacked(15, false); // indexed by row + col&lt;br /&gt;
vector&amp;lt;bool&amp;gt; diag2Attacked(15, false); // indexed by row - col + (n - 1)&lt;br /&gt;
&lt;br /&gt;
long long answer = 0;&lt;br /&gt;
&lt;br /&gt;
void place(int row) {&lt;br /&gt;
    if (row == n) {&lt;br /&gt;
        answer++;&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    for (int col = 0; col &amp;lt; n; col++) {&lt;br /&gt;
        if (grid[row][col] == &#039;*&#039;) continue;               // reserved square&lt;br /&gt;
        if (colAttacked[col]) continue;&lt;br /&gt;
        if (diag1Attacked[row + col]) continue;&lt;br /&gt;
        if (diag2Attacked[row - col + n - 1]) continue;&lt;br /&gt;
&lt;br /&gt;
        // place queen&lt;br /&gt;
        colAttacked[col] = true;&lt;br /&gt;
        diag1Attacked[row + col] = true;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = true;&lt;br /&gt;
&lt;br /&gt;
        place(row + 1);&lt;br /&gt;
&lt;br /&gt;
        // backtrack: undo placement&lt;br /&gt;
        colAttacked[col] = false;&lt;br /&gt;
        diag1Attacked[row + col] = false;&lt;br /&gt;
        diag2Attacked[row - col + n - 1] = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    grid.resize(n);&lt;br /&gt;
    for (auto &amp;amp;row : grid) cin &amp;gt;&amp;gt; row;&lt;br /&gt;
&lt;br /&gt;
    place(0);&lt;br /&gt;
    cout &amp;lt;&amp;lt; answer &amp;lt;&amp;lt; endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it&#039;s &#039;&#039;&#039;not necessary&#039;&#039;&#039; to actually mark the square in &amp;lt;code&amp;gt;grid&amp;lt;/code&amp;gt; as a queen (&#039;Q&#039;); the three boolean arrays already fully capture every constraint we need to check, so there&#039;s nothing to gain from also mutating the grid string.&lt;br /&gt;
&lt;br /&gt;
== Complexity ==&lt;br /&gt;
&lt;br /&gt;
* Row 0 has at most 8 choices, row 1 has at most 7 (one column already taken), and so on — giving a rough bound of &#039;&#039;&#039;O(n!)&#039;&#039;&#039;, possibly with an extra factor of n from the per-row scan: &#039;&#039;&#039;O(n! · n)&#039;&#039;&#039;.&lt;br /&gt;
* In practice it&#039;s &#039;&#039;&#039;much faster&#039;&#039;&#039; than this bound suggests, because diagonal constraints prune the search tree aggressively. On the empty 8×8 board (the worst case, since nothing is reserved), the recursion has exactly &#039;&#039;&#039;92 leaves&#039;&#039;&#039; (the well-known number of solutions to the 8-queens problem) and runs in about a millisecond.&lt;br /&gt;
* This approach does &#039;&#039;&#039;not&#039;&#039;&#039; scale to large n (e.g. n = 1000). Placing n non-attacking queens under arbitrary reserved-square constraints is a much harder problem in general — for large boards you need entirely different techniques (or the instance may simply be intractable).&lt;br /&gt;
&lt;br /&gt;
== What Is Backtracking? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Backtracking&#039;&#039;&#039; is the name for exactly this pattern: recursively try a choice, recurse further assuming that choice, and if a later step hits a dead end (no valid moves possible), &#039;&#039;&#039;undo the choice&#039;&#039;&#039; (&amp;quot;backtrack&amp;quot;) and try the next alternative. The name comes from the fact that the recursion tree doesn&#039;t just go forward — it routinely retreats and retries.&lt;br /&gt;
&lt;br /&gt;
Some useful mental models:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s the same technique behind &#039;&#039;&#039;Sudoku solvers&#039;&#039;&#039;: try a digit, recurse, and if a contradiction is eventually reached, undo and try a different digit.&lt;br /&gt;
* Backtracking is typically used to find &#039;&#039;&#039;one valid solution&#039;&#039;&#039; (Sudoku) or to &#039;&#039;&#039;count all valid solutions&#039;&#039;&#039; (this problem) when there&#039;s no faster closed-form or DP approach — often because the problem is NP-hard in general.&lt;br /&gt;
* Backtracking problems are almost always about a &amp;quot;good enough&amp;quot; solution rather than a provably optimal one. There is nearly always room to add smarter pruning:&lt;br /&gt;
** Example: if you can detect &#039;&#039;before&#039;&#039; recursing that some later row has only one legal column left, you can propagate that constraint early and cut off huge unproductive branches. This kind of look-ahead pruning can make backtracking &#039;&#039;&#039;hundreds or even thousands of times faster&#039;&#039;&#039; — but it&#039;s an enhancement on top of the base algorithm, not a change to its fundamental structure.&lt;br /&gt;
&lt;br /&gt;
== Key Takeaways ==&lt;br /&gt;
&lt;br /&gt;
* Small constraints (like n = 8) are a strong hint that the intended solution is exponential/factorial-time backtracking.&lt;br /&gt;
* Always pair &amp;quot;make a move&amp;quot; with &amp;quot;undo the move&amp;quot; (backtrack) after the recursive call returns — this is what makes the search correct.&lt;br /&gt;
* For diagonal checks on a grid, remember:&lt;br /&gt;
** &amp;lt;code&amp;gt;row + col&amp;lt;/code&amp;gt; is constant along one diagonal direction.&lt;br /&gt;
** &amp;lt;code&amp;gt;row − col&amp;lt;/code&amp;gt; is constant along the other (add an offset of &amp;lt;code&amp;gt;n − 1&amp;lt;/code&amp;gt; to keep indices non-negative).&lt;br /&gt;
* Prefer O(1) incremental state (boolean arrays) over re-scanning the board on every check — it turns an already-fast solution into a very fast one.&lt;br /&gt;
* Global arrays/variables are common in competitive programming for exactly this kind of state — avoids passing/copying containers on every recursive call.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=370</id>
		<title>Template:DailyJournalPreload</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=370"/>
		<updated>2026-09-03T03:57:33Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODOs ==&lt;br /&gt;
{{{todos|}}}&lt;br /&gt;
&lt;br /&gt;
== Learnings ==&lt;br /&gt;
* {{{learnings|}}}&lt;br /&gt;
&lt;br /&gt;
== Thoughts ==&lt;br /&gt;
{{{notes|}}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=364</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=364"/>
		<updated>2026-09-01T09:18:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{#time:Y|+5 hours 30 minutes}}/{{#time:m|+5 hours 30 minutes}}/{{#time:d|+5 hours 30 minutes}}|veaction=edit&amp;amp;preload=Template:DailyJournalPreload}}}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=361</id>
		<title>Template:DailyJournalPreload</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=361"/>
		<updated>2026-08-31T12:16:00Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODOs ==&lt;br /&gt;
* {{{todos|}}}&lt;br /&gt;
&lt;br /&gt;
== Learnings ==&lt;br /&gt;
* {{{learnings|}}}&lt;br /&gt;
&lt;br /&gt;
== Thoughts ==&lt;br /&gt;
{{{notes|}}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=359</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=359"/>
		<updated>2026-08-31T12:14:06Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{#time:Y}}/{{#time:m}}/{{#time:d}}|veaction=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=358</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=358"/>
		<updated>2026-08-31T09:25:20Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{#time:Y}}/{{#time:m}}/{{#time:Y-m-d}}|veaction=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=354</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=354"/>
		<updated>2026-08-31T05:29:19Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Private:Journal/{{#time:Y}}/{{#time:m}}/{{#time:Y-m-d}}|action=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=352</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Main_Page&amp;diff=352"/>
		<updated>2026-08-31T05:23:36Z</updated>

		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:scratchpad}}&lt;br /&gt;
Welcome to &#039;&#039;&#039;scratchpad&#039;&#039;&#039; — my personal notes, diagrams, and random thoughts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sc-adminonly&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;sc-newnote&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browse notes ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;sc-notes-tree&amp;quot;&amp;gt;Loading notes…&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:AllPages|Flat list of all pages]]&lt;br /&gt;
* [{{fullurl:Journal/{{#time:Y}}/{{#time:m}}/{{#time:Y-m-d}}|action=edit&amp;amp;preload=Template:DailyJournalPreload}} Create today&#039;s note]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=351</id>
		<title>Template:DailyJournalPreload</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=Template:DailyJournalPreload&amp;diff=351"/>
		<updated>2026-08-31T05:23:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;== TODOs == * {{{todos|}}}  == Learnings == * {{{learnings|}}}  == Notes == {{{notes|}}}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODOs ==&lt;br /&gt;
* {{{todos|}}}&lt;br /&gt;
&lt;br /&gt;
== Learnings ==&lt;br /&gt;
* {{{learnings|}}}&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
{{{notes|}}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://myscratchpad.is-a.dev/index.php?title=DSA/CSES_2Knights&amp;diff=350</id>
		<title>DSA/CSES 2Knights</title>
		<link rel="alternate" type="text/html" href="https://myscratchpad.is-a.dev/index.php?title=DSA/CSES_2Knights&amp;diff=350"/>
		<updated>2026-08-31T05:04:38Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;== Non-Attacking Knights on a k×k Board ==  &amp;#039;&amp;#039;&amp;#039;Problem.&amp;#039;&amp;#039;&amp;#039; For every board size &amp;lt;math&amp;gt;k = 1, 2, \dots, n&amp;lt;/math&amp;gt;, count the number of ways to place &amp;#039;&amp;#039;two&amp;#039;&amp;#039; knights on a &amp;lt;math&amp;gt;k \times k&amp;lt;/math&amp;gt; chessboard so that they do not attack each other.  The core is instead of calculating the possible combinations of placements which is confusing we can do &amp;#039;&amp;#039;total_possibilities - attacking_squares&amp;#039;&amp;#039;  ----  === Step 1: Total ways to place two knights, ignoring attacks ===  A &amp;lt;math&amp;gt;k...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Non-Attacking Knights on a k×k Board ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Problem.&#039;&#039;&#039; For every board size &amp;lt;math&amp;gt;k = 1, 2, \dots, n&amp;lt;/math&amp;gt;, count the number of ways to place &#039;&#039;two&#039;&#039; knights on a &amp;lt;math&amp;gt;k \times k&amp;lt;/math&amp;gt; chessboard so that they do not attack each other.&lt;br /&gt;
&lt;br /&gt;
The core is instead of calculating the possible combinations of placements which is confusing we can do &#039;&#039;total_possibilities - attacking_squares&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Total ways to place two knights, ignoring attacks ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;math&amp;gt;k \times k&amp;lt;/math&amp;gt; board has &amp;lt;math&amp;gt;k^2&amp;lt;/math&amp;gt; squares. Placing two (identical, unlabeled) knights on two different squares is just &amp;quot;choose 2 squares out of &amp;lt;math&amp;gt;k^2&amp;lt;/math&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\binom{k^2}{2} = \frac{k^2(k^2-1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the total number of placements &#039;&#039;&#039;before&#039;&#039;&#039; removing the ones where the knights attack each other.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Counting the attacking pairs ===&lt;br /&gt;
&lt;br /&gt;
A knight standing at square &amp;lt;math&amp;gt;(x, y)&amp;lt;/math&amp;gt; attacks any square that is offset by one of these 8 vectors:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset (dx, dy)&lt;br /&gt;
|-&lt;br /&gt;
| (1, 2) || (1, −2) || (−1, 2) || (−1, −2)&lt;br /&gt;
|-&lt;br /&gt;
| (2, 1) || (2, −1) || (−2, 1) || (−2, −1)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Notice: in &#039;&#039;&#039;every&#039;&#039;&#039; one of these 8 vectors, the two numbers &amp;lt;math&amp;gt;|dx|&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;|dy|&amp;lt;/math&amp;gt; are just 1 and 2 in some order, with some sign.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How many placements exist for one fixed offset (dx, dy)?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For the pair of squares &amp;lt;math&amp;gt;(x,y)&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;(x+dx, y+dy)&amp;lt;/math&amp;gt; to both lie on the board, &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; has &amp;lt;math&amp;gt;k - |dx|&amp;lt;/math&amp;gt; valid choices, and &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; has &amp;lt;math&amp;gt;k - |dy|&amp;lt;/math&amp;gt; valid choices. So the count is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;(k - |dx|)(k - |dy|)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since &amp;lt;math&amp;gt;\{|dx|, |dy|\} = \{1, 2\}&amp;lt;/math&amp;gt; for all 8 vectors, this is always:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;(k-1)(k-2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(No need to clamp negative values to zero — if &amp;lt;math&amp;gt;k=1&amp;lt;/math&amp;gt;, the factor &amp;lt;math&amp;gt;(k-1)=0&amp;lt;/math&amp;gt; already kills the product; if &amp;lt;math&amp;gt;k=2&amp;lt;/math&amp;gt;, the factor &amp;lt;math&amp;gt;(k-2)=0&amp;lt;/math&amp;gt; does the same. The algebra takes care of small boards automatically.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summing over all 8 offsets&#039;&#039;&#039; gives the total number of &#039;&#039;ordered&#039;&#039; attacking pairs (i.e., &amp;quot;knight A attacks square B&amp;quot; counted separately from &amp;quot;knight B attacks square A&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;8(k-1)(k-2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But an unordered &#039;&#039;pair&#039;&#039; of squares gets counted twice this way (once in each direction), so the number of unordered attacking pairs is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E(k) = \frac{8(k-1)(k-2)}{2} = 4(k-1)(k-2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Subtract to get non-attacking pairs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\text{Answer}(k) = \binom{k^2}{2} - E(k) = \frac{k^2(k^2-1)}{2} - 4(k-1)(k-2)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Simplify into one closed-form polynomial ===&lt;br /&gt;
&lt;br /&gt;
Expand each piece separately.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;First term:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{k^2(k^2-1)}{2} = \frac{k^4 - k^2}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Second term:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;math&amp;gt;4(k-1)(k-2) = 4(k^2 - 3k + 2) = 4k^2 - 12k + 8&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Put both over a common denominator of 2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\text{Answer}(k) = \frac{k^4 - k^2}{2} - \frac{8k^2 - 24k + 16}{2}&lt;br /&gt;
= \frac{k^4 - k^2 - 8k^2 + 24k - 16}{2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Combine like terms (&amp;lt;math&amp;gt;-k^2 - 8k^2 = -9k^2&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\text{Answer}(k) = \frac{k^4 - 9k^2 + 24k - 16}{2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 5: Sanity check against the example ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! k !! Answer(k)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 6&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 28&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 96&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 252&lt;br /&gt;
|-&lt;br /&gt;
| 6 || 550&lt;br /&gt;
|-&lt;br /&gt;
| 7 || 1056&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 1848&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Matches the sample output exactly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Intuition for k=1 and k=2:&#039;&#039;&#039; On a 1×1 board there&#039;s only one square, so you can&#039;t even place two knights (0 ways). On a 2×2 board, &amp;lt;math&amp;gt;\binom{4}{2}=6&amp;lt;/math&amp;gt; pairs exist, and a knight move needs at least a 3-wide gap in one direction, so &#039;&#039;none&#039;&#039; of them attack — all 6 count.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Step 6: Implementation ===&lt;br /&gt;
&lt;br /&gt;
Since the formula is closed-form, each answer is &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; to compute, so the whole solution is &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; — trivially fast for &amp;lt;math&amp;gt;n \le 10000&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def f(k):&lt;br /&gt;
    return (pow(k, 4) - 9 * pow(k, 2) + 24 * k - 16) // 2&lt;br /&gt;
&lt;br /&gt;
n = int(input())&lt;br /&gt;
&lt;br /&gt;
for i in range(1, n + 1):&lt;br /&gt;
    print(f(i))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the division by 2 is safe as integer division (&amp;lt;code&amp;gt;//&amp;lt;/code&amp;gt;) because &amp;lt;math&amp;gt;k^4 - 9k^2 + 24k - 16&amp;lt;/math&amp;gt; is always even — this follows directly from the derivation, since it came from summing two integer-valued combinatorial counts (&amp;lt;math&amp;gt;\binom{k^2}{2}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E(k)&amp;lt;/math&amp;gt;) that are each themselves always integers, and their difference stays an integer after the &amp;lt;math&amp;gt;\times 2&amp;lt;/math&amp;gt; common denominator was cleared.&lt;br /&gt;
&lt;br /&gt;
[[Category:DSA]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>