USACO 2017 US Open · Bronze · all three problems
Problem 1 — The Lost Cow
Statement
Farmer John stands at integer position x on a number line. Bessie is hiding at integer position y. FJ searches with a fixed zigzag rule: step 1 to the right, step 2 to the left, step 4 to the right, step 8 to the left, … doubling and alternating direction. He stops the instant his current sweep covers y (i.e. y lies between his previous position and his new position, inclusive). Output the total distance he walks.
Constraints
- 0 ≤ x, y ≤ 1000, x ≠ y.
- x and y are integers.
- Time limit: 2s.
Key idea
Just simulate. At step k (k = 0, 1, 2, …) FJ moves a signed distance of (k even ? +1 : −1) · 2k from his current position. After each step, check whether y lies on the closed segment between the old and new position. If yes, the total distance is (previous accumulated distance) + |y − old position|; otherwise add 2k and continue. Because the search is guaranteed to find y within roughly 9|x−y| distance, you never need k larger than ~12.
Complexity target
O(log |x − y|) steps; well under a microsecond.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int x, y; cin >> x >> y;
long long pos = x, dist = 0, step = 1;
int sign = +1; // first move is to the right
while (true) {
long long npos = pos + (long long)sign * step;
long long lo = min(pos, npos), hi = max(pos, npos);
if (lo <= y && y <= hi) {
dist += abs(y - pos);
break;
}
dist += step;
pos = npos;
step *= 2;
sign = -sign;
}
cout << dist << "\n";
}
Pitfalls
- Direction convention. Re-read the statement: the first step is +1, the second is −2. If you flip the first sign your sample output will be wrong.
- Coverage check is inclusive. If y equals the endpoint reached at the end of a step, that step is the terminating step.
- Don't pre-compute a closed form. The geometry is fiddly; simulation in < 30 lines is the safe play.
- Distance, not number of steps. The answer is total walked distance.
Problem 2 — Bovine Genomics
Statement
There are N spotty cows and N plain cows. Each has a genome of length M over the alphabet {A, C, G, T}. Count the number of column indices j (0-indexed or 1-indexed, your choice) such that the multiset of characters at column j among the spotty cows is disjoint from the multiset of characters at column j among the plain cows. (Equivalently: no character appears at column j in both groups.) Such a column "explains" spottiness on its own.
Constraints
- 1 ≤ N, M ≤ 100.
- Genomes are strings of length M over {A, C, G, T}.
- Time limit: 2s.
Key idea
For each column j, build two 4-bit masks — one of letters appearing in the spotty group at j, and one of letters appearing in the plain group. The column qualifies if the AND of the two masks is 0. O(N·M) over a tiny alphabet.
Complexity target
O(N · M) = 104. Trivial.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int idx(char c) {
switch (c) { case 'A': return 0; case 'C': return 1;
case 'G': return 2; default: return 3; } // 'T'
}
int main() {
int N, M; cin >> N >> M;
vector<string> spot(N), plain(N);
for (auto& s : spot) cin >> s;
for (auto& s : plain) cin >> s;
int ans = 0;
for (int j = 0; j < M; ++j) {
int sm = 0, pm = 0;
for (int i = 0; i < N; ++i) sm |= 1 << idx(spot[i][j]);
for (int i = 0; i < N; ++i) pm |= 1 << idx(plain[i][j]);
if ((sm & pm) == 0) ++ans;
}
cout << ans << "\n";
}
Pitfalls
- "Disjoint character sets" is the rule. It's not "all spotty share one letter" — spotty rows can mix letters too, as long as none of them appears in any plain row at the same column.
- One column at a time. Don't try to be clever across columns; the Silver/Gold versions are where combinations of columns matter.
- 4-character alphabet. A 4-bit mask is the cleanest representation; sets/sort/uniqued vectors also fine.
Problem 3 — Modern Art
Statement
Picowso paints 9 axis-aligned rectangles, in colors 1 through 9, on an N×N canvas. The canvas starts as zeros. Each color is used at most once, and later colors can overwrite earlier ones. Given the final canvas, count how many of the 9 colors could have been the very first color painted — i.e. colors that are not required to lie on top of any other visible color.
Constraints
- 1 ≤ N ≤ 10.
- Each grid cell is an integer 0..9 (0 = blank).
- Each color 1..9 is either absent or appears as one rectangle's residual visible region.
- Time limit: 2s.
Key idea
For each visible color c, compute the bounding box of its visible cells. If every cell inside that bounding box is either color c or 0, then color c could be the first painted (nothing sits beneath it). If any cell inside is a different non-zero color, then c had to be painted before that other color, so c was not first. Count colors whose bounding box has no foreign non-zero cells. (Colors that don't appear at all in the grid are buried under others and cannot be "first painted" in the visible sense — check the official sample to confirm.)
Complexity target
O(N2 · 9) = 900. Trivial.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int N; cin >> N;
vector<vector<int>> g(N, vector<int>(N));
for (auto& r : g) for (auto& x : r) cin >> x;
// Per color c=1..9: bounding box of cells where g==c.
int lo_r[10], hi_r[10], lo_c[10], hi_c[10];
bool present[10] = {};
for (int c = 1; c <= 9; ++c) {
lo_r[c] = lo_c[c] = INT_MAX;
hi_r[c] = hi_c[c] = INT_MIN;
}
for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {
int c = g[i][j];
if (c == 0) continue;
present[c] = true;
lo_r[c] = min(lo_r[c], i); hi_r[c] = max(hi_r[c], i);
lo_c[c] = min(lo_c[c], j); hi_c[c] = max(hi_c[c], j);
}
int ans = 0;
for (int c = 1; c <= 9; ++c) {
if (!present[c]) continue;
bool first_ok = true;
for (int i = lo_r[c]; i <= hi_r[c] && first_ok; ++i)
for (int j = lo_c[c]; j <= hi_c[c] && first_ok; ++j)
if (g[i][j] != 0 && g[i][j] != c) first_ok = false;
if (first_ok) ++ans;
}
cout << ans << "\n";
}
Pitfalls
- "Could be first" means nothing else was painted before it. Translate: no other non-zero color lies inside its bounding box.
- Zero cells inside the bounding box are fine. The rectangle covered them, but a later color may have been painted — no, 0 means truly blank because the rectangle covered then was overwritten by nothing visible — tricky! Re-read: 0 cells inside a visible color's bbox indicate the color is not a solid rectangle in the final image, which actually means another color was painted over it. The official editorial treats 0s inside the bbox as "this color cannot be first."
- Bronze N ≤ 10. Brute force is the intended path; don't over-engineer.
What Bronze 2017 US Open was actually testing
- P1 — faithful simulation. Read carefully, code the rule, stop at the right moment.
- P2 — per-column independence. Recognize that the answer decomposes column-by-column.
- P3 — bounding boxes as an "is this rectangle still intact?" test. A foundational pattern that returns at Gold and Platinum in the same contest.