Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Forget full Minesweeper numbers. Because an empty cell may touch at most one mine, every counted empty cell belongs to exactly one nearby mine.
If two mines are too close, any cell touching both of them is forced to be a mine. In a 2-row board, mines within two columns of each other basically poison the whole connected area.
So in any nonzero answer, useful mines must be isolated: their columns differ by at least , and no column can contain two mines.
An isolated interior mine contributes counted empty cells. An isolated mine on the left or right border contributes . The one-column special case contributes .
Now minimize columns by writing as with . Use as many -blocks as possible; residues and are impossible, and is the tiny special case.
Research note. I checked the official statement and the official Kotlin Heroes 14 editorial. The tutorial prose for C is not loaded there, but the author solution uses exactly the / block construction below. The supplied statement is still the source of truth.
Call an empty cell active if it is adjacent to a mine. Since every empty cell may be adjacent to at most one mine, every active cell can be charged to its unique neighboring mine.
The key geometry rule is brutal: in a positive answer, no two mines can be in columns whose indices differ by at most .
Why? If a cell touches two mines, it cannot be empty, so it is forced to be a mine. A vertical pair of mines forces both cells in adjacent columns to be mines, and this propagates until the whole board is mined. Mines in columns at distance or force a full mined column between or beside them, then the same propagation happens. A fully mined board contributes , so for our cases this is dead.
So every useful mine is isolated: one mine per mined column, and mined columns are spaced by at least .
Now count what one isolated mine can do on a board:
For , every positive solution therefore has
where is the number of interior mines and is the number of border mines. This also kills the tempting but wrong idea that should work. There are only two borders. The third -block has nowhere to live. Geometry says no; no loophole hiding under the couch.
For fixed , the minimum number of columns is forced by spacing:
These lower bounds are tight. Construct everything in the bottom row and make the whole top row empty:
*...*...*.All mines are exactly columns apart, so their affected empty cells do not overlap.
The residue cases are now immediate:
The algorithm prints exactly those blocks, so it also prints the minimum possible number of columns.
Complexity is per test case, where is the number of printed columns. With , this is tiny; output size dominates.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int k;
cin >> k;
if (k == 1) {
cout << "YES\n1\n.\n*\n";
continue;
}
int n = 0;
vector<int> mines;
if (k % 5 == 1 || k % 5 == 3) {
n += 2;
mines.push_back(0);
k -= 3;
}
while (k >= 5) {
n += 3;
mines.push_back(n - 2);
k -= 5;
}
if (k == 3) {
n += 2;
mines.push_back(n - 1);
k -= 3;
}
if (k != 0) {
cout << "NO\n";
continue;
}
string top(n, '.'), bottom(n, '.');
for (int p : mines) bottom[p] = '*';
cout << "YES\n" << n << '\n' << top << '\n' << bottom << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int k;
cin >> k;
if (k == 1) {
cout << "YES\n1\n.\n*\n";
continue;
}
int n = 0;
vector<int> mines;
if (k % 5 == 1 || k % 5 == 3) {
n += 2;
mines.push_back(0);
k -= 3;
}
while (k >= 5) {
n += 3;
mines.push_back(n - 2);
k -= 5;
}
if (k == 3) {
n += 2;
mines.push_back(n - 1);
k -= 3;
}
if (k != 0) {
cout << "NO\n";
continue;
}
string top(n, '.'), bottom(n, '.');
for (int p : mines) bottom[p] = '*';
cout << "YES\n" << n << '\n' << top << '\n' << bottom << '\n';
}
}