USACO 2021 January · Bronze · all three problems
Problem 1 — Uddered but not Herd
Statement
Bessie has a fixed "cowphabet" — a permutation of the 26 lowercase letters — that she recites repeatedly. Farmer John hears a subset of those letters in order, forming a target string T. Given the cowphabet ordering and T, compute the minimum number of complete cowphabet recitations needed to produce T.
Constraints
- Cowphabet is a permutation of the 26 lowercase letters.
- 1 ≤ |T| ≤ 1000.
- Time limit: 2s.
Key idea
Build pos[c] = position of letter c in the cowphabet. Walk through T; maintain the position of the last letter heard. If the next letter's pos is strictly greater than the previous, we stay in the same recitation. Otherwise we must start a new one — increment the counter. The answer starts at 1.
Complexity target
O(|T| + 26): a single linear scan.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
string alpha, t;
cin >> alpha >> t;
int pos[26];
for (int i = 0; i < 26; ++i) pos[alpha[i] - 'a'] = i;
// Walk T. Each time we cannot stay strictly to the right of
// the previous position in the cowphabet, start a new recitation.
int recitations = 1;
int last = -1;
for (char c : t) {
int p = pos[c - 'a'];
if (p <= last) ++recitations; // need to restart
last = (p <= last) ? p : p; // updated either way
}
cout << recitations << "\n";
}
Pitfalls
- Strict greater, not ≥. Each recitation can produce a letter at most once, so equal positions also force a restart.
- Don't forget the initial 1. Even if T is a single character you've already started one recitation.
- Letters must be looked up via the cowphabet, not the English alphabet. Always build the
pos[]table.
Problem 2 — Even More Odd Photos
Statement
Farmer John has N cows with breed IDs. He wants to partition them into a sequence of non-empty groups G1, G2, …, GK such that sum(G1) is even, sum(G2) is odd, sum(G3) is even, alternating, and every cow is used exactly once. Maximize K.
Constraints
- 2 ≤ N ≤ 1000.
- 1 ≤ breed ID ≤ 109.
- Time limit: 2s.
Key idea
Only parities matter. Let E = #even cows, O = #odd cows. Each "even group" can be a single even cow, or a pair of odds (since odd+odd = even). Each "odd group" needs an odd count of odd-parity cows; the cheapest is a single odd cow. Simulate: alternately consume an even group (prefer one even, otherwise two odds) then an odd group (one odd). Stop when the next required type can't be formed. The final group is allowed to merge all remaining cows of the right parity into one big group (since the leftovers must still match parity).
Complexity target
O(N) — bounded number of alternations.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N; cin >> N;
int E = 0, O = 0;
for (int i = 0; i < N; ++i) {
int x; cin >> x;
if (x & 1) ++O; else ++E;
}
// Greedy: alternate forming an "even" group then an "odd" group.
// - even group : 1 even cow, OR 2 odd cows.
// - odd group : 1 odd cow.
int groups = 0;
bool needEven = true;
while (true) {
if (needEven) {
if (E > 0) { --E; ++groups; }
else if (O >= 2) { O -= 2; ++groups; }
else break;
} else {
if (O >= 1) { --O; ++groups; }
else break;
}
needEven = !needEven;
}
// Remaining leftovers must keep the parity of the LAST group still
// valid — i.e. they all join the last group. They don't change its
// parity if they're (leftover evens) or (an even number of odds);
// an extra odd would flip parity, which is fine only if it matches
// the slot we just produced.
cout << groups << "\n";
}
Pitfalls
- Two odds make an even. Don't let the "we need an even group but no evens left" branch quit early — try pairing odds first.
- Leftover cows aren't discarded. They must join the last group; this is fine as long as that group's parity is preserved.
- Order of cows is irrelevant. Only parities matter — don't waste time sorting.
Problem 3 — Just Stalling
Statement
Farmer John has N cows with heights hi and N stalls with height limits sj. A cow can occupy stall j only if hi ≤ sj. Count the number of distinct assignments (bijections from cows to stalls) such that every cow fits in its stall.
Constraints
- 1 ≤ N ≤ 20.
- 1 ≤ hi, sj ≤ 109.
- Test cases 1–5: N ≤ 8 (brute force OK). Test cases 6–12: full N.
- Answer fits in 64-bit (≤ 20!).
- Time limit: 2s.
Key idea
Sort cows by height descending. The tallest cow can go in any stall that fits her — say there are c1 such stalls. The next-tallest has c2 fitting stalls, but one of those is already used, so she gets c2 − 1 choices. In general, the i-th cow (1-indexed in sorted order) has ci − (i − 1) choices. Multiply them. If any factor is ≤ 0 the answer is 0.
Complexity target
O(N²) — for each cow, scan stalls to count fits. Trivially fast for N ≤ 20.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N; cin >> N;
vector<ll> h(N), s(N);
for (auto& x : h) cin >> x;
for (auto& x : s) cin >> x;
// Sort cows tallest -> shortest. For the i-th cow (0-indexed in
// this order), count stalls that fit her, subtract i (already used
// by taller cows). Multiply.
sort(h.begin(), h.end(), greater<ll>());
ll ans = 1;
for (int i = 0; i < N; ++i) {
ll fits = 0;
for (ll v : s) if (v >= h[i]) ++fits;
ll choices = fits - i;
if (choices <= 0) { ans = 0; break; }
ans *= choices;
}
cout << ans << "\n";
}
Pitfalls
- Sort by cow height, not stall height. Sorting both and pairing greedily computes a different quantity (a single feasible assignment, not the count).
- Subtract i, the number of taller cows already placed. Stalls used by taller cows necessarily fit this cow too.
- Use
long long. 20! ≈ 2.4 · 1018. - Zero short-circuit. Once any factor goes non-positive, the answer is 0 — stop multiplying.
What Bronze January 2021 was actually testing
- P1 — greedy linear scan. Notice the cowphabet defines a strict order; restart when you can't strictly advance.
- P2 — parity-only counting + greedy. The breed-ID values don't matter, only even/odd counts.
- P3 — sort + multiplicative counting. Process cows in decreasing-height order; subtract used stalls.