<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

224. Little Queens
time limit per test: 0.75 sec.
memory limit per test: 65536 KB
input: standard
output: standard



Well, you might have heard about a curious boy Petya who likes to learn the number of ways one can put k identical chess pieces on a chessboard of size n× n so that no two of them are in the attacking positions. He have solved the problems for bishops, rooks and kings. Recently he has met Farmer John and told him about that.

Impressed FJ has decided to teach his cows to play chess. The first question Bessie asked on the first lesson was: "What about the number of ways one can put k queens on a chessboard of size n × n, so that no two of them are in the attacking positions?"

The queen can move diagonally, horizonatally and vertically, thus combining the properties of a bishop and a rook. Two queens are in the attacking positions if they are on the path of each other.

Input

The input file contains two integers n (1 ≤ n ≤ 10) and k (0 ≤ k ≤ n2).

Output

Print a line containing the total number of ways one can put the given number of queens on a chessboard of the given size so that no two of them are in attacking positions.

Sample test(s)

Input
Test #1

3 2

Test #2

4 4

Output
Test #1

8

Test #2

2
Author:	Andrew Stankevich
Resource:	Little Chess Pieces Series, SPb IFMO 2003-2004 Authumn Training Sessions
Date:	2003-10-08

<|response|>
1. Abridged Problem Statement  
Given an n×n chessboard (1 ≤ n ≤ 10) and an integer k (0 ≤ k ≤ n²), count the number of ways to place k identical queens so that no two attack each other (i.e. no two share a row, column, or diagonal).

2. Key Observations  
- A queen attacks along its row, its column, and both diagonals.  
- Since queens are identical, the order of placement doesn’t matter; we just count distinct sets of k squares.  
- We can build solutions row by row. In each row we either place exactly one queen or none.  
- If we ever need to place more queens than rows remaining, we can prune that branch.  
- Two classic ways to track attacks:  
  a. A 2D array `attacked[r][c]` counting how many queens attack square (r,c).  
  b. Three bitmasks for columns and the two diagonal directions, shifting them as we go down the board.

3. Full Solution Approach  
We describe the 2D-array “attacked” approach here; the Python bitmask variant appears in section 5.

- Maintain an n×n integer array `attacked`, initially all zeros.  
  attacked[r][c] > 0 means (r,c) is under attack by at least one placed queen.  
- Define a recursive function `dfs(row, k_left)` that returns the number of ways to place `k_left` queens in rows `row..n-1`.  
  1. If `k_left == 0`, we have placed all queens—count 1 valid configuration (any remaining rows are empty).  
  2. If `row == n` but `k_left > 0`, no more rows remain—count 0.  
  3. Prune: if `k_left > (n - row)`, we cannot place enough one-queen-per-row to reach k, so return 0.  
  4. First option: place no queen in this row → `ways = dfs(row+1, k_left)`.  
  5. Second option (if `k_left > 0`): for each column `c` in [0..n-1], if `attacked[row][c] == 0` (safe), then:  
     a. Mark all squares attacked by placing a queen at (row,c) by calling `mark(row,c,+1)`.  
     b. Add `dfs(row+1, k_left-1)` to `ways`.  
     c. Unmark with `mark(row,c,-1)` to backtrack.  
- The helper `mark(r,c,delta)` will iterate over the row, column, and the four diagonals passing through (r,c), adding `delta` (+1 or –1) to each attacked cell. We correct the triple-counting at (r,c) itself by subtracting `3*delta`.

Overall complexity is acceptable for n≤10 and k≤n², especially with the “must place ≤1 queen per row” pruning.

4. C++ Solution
```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n, k;

void change_queen(int row, int col, vector<vector<int>>& attacked, int delta) {
    for(int i = 0; i < n; i++) {
        attacked[row][i] += delta;
        attacked[i][col] += delta;
        if(row + i < n && col + i < n) {
            attacked[row + i][col + i] += delta;
        }

        if(row + i < n && col - i >= 0) {
            attacked[row + i][col - i] += delta;
        }

        if(row - i >= 0 && col + i < n) {
            attacked[row - i][col + i] += delta;
        }

        if(row - i >= 0 && col - i >= 0) {
            attacked[row - i][col - i] += delta;
        }
    }

    attacked[row][col] -= 3 * delta;
}

int brute(int row, int k, vector<vector<int>>& attacked) {
    if(k > n - row) {
        return 0;
    }

    if(row == n) {
        return 1;
    }

    int ans = brute(row + 1, k, attacked);
    for(int col = 0; col < n; col++) {
        if(k && !attacked[row][col]) {
            change_queen(row, col, attacked, 1);
            ans += brute(row + 1, k - 1, attacked);
            change_queen(row, col, attacked, -1);
        }
    }

    return ans;
}

void read() { cin >> n >> k; }

void solve() {
    // Backtracking row by row, placing at most one queen per row. attacked[r][c]
    // counts how many already-placed queens attack cell (r, c) along a row,
    // column or diagonal, so a cell is free iff its counter is zero; placing or
    // removing a queen bumps every cell on its four lines by +/-1 (the queen's
    // own cell gets corrected for being counted on all four lines). At each row
    // we either skip it or try every free column, decrementing the remaining
    // queen budget k. The pruning k > n - row cuts branches that cannot fit the
    // remaining queens, and reaching row == n with the placements done counts as
    // one valid arrangement.

    vector<vector<int>> attacked(n, vector<int>(n, 0));
    cout << brute(0, k, attacked) << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

5. Python Implementation with Detailed Comments  
This variant uses bitmasks for columns and diagonals plus memoization for speed.

```python
import sys
sys.setrecursionlimit(10**7)
from functools import lru_cache

def count_ways(n, k):
    # ALL columns mask: lower n bits = 1
    ALL = (1 << n) - 1

    @lru_cache(None)
    def dfs(row, placed, cols, d1, d2):
        # placed = number of queens so far
        # row = next row index
        # cols = bitmask of occupied columns
        # d1   = bitmask of main-diagonals under attack (row+col)
        # d2   = bitmask of anti-diagonals under attack (row-col + (n-1))
        
        # If we've placed k queens, any remaining rows are empty
        if placed == k:
            return 1
        # If out of rows but not enough queens placed
        if row == n:
            return 0
        # Prune: even if we place one queen per remaining row we can't reach k
        if placed + (n - row) < k:
            return 0
        
        ways = 0
        # Option 1: skip this row (no queen here)
        # Shift diagonals for the next row:
        #   main-diagonal mask shifts left by 1
        #   anti-diagonal mask shifts right by 1
        ways += dfs(row+1, placed,
                    cols,
                    (d1 << 1) & ALL, 
                    (d2 >> 1))
        
        # Option 2: place a queen in any free column
        attacked = cols | d1 | d2
        free = (~attacked) & ALL
        while free:
            # pick the lowest-set bit
            bit = free & -free
            free -= bit
            ways += dfs(row+1,
                        placed+1,
                        cols | bit,
                        ((d1 | bit) << 1) & ALL,
                        (d2 | bit) >> 1)
        return ways

    return dfs(0, 0, 0, 0, 0)

if __name__ == "__main__":
    n, k = map(int, sys.stdin.readline().split())
    print(count_ways(n, k))
```

Explanation of the bitmask fields:  
- `cols` has 1-bits in columns already occupied by queens.  
- `d1` (main diagonals) has 1-bits where row+col is under attack. To move from one row to the next, shift `d1` left by 1.  
- `d2` (anti-diagonals) has 1-bits where row−col+(n−1) is under attack; shift it right by 1 when going down.  
We combine them to find `attacked` positions, then iterate over each free bit to place the next queen. Memoization avoids recomputing identical states.