Alternating Box Towers
National Olympiad — National round (2023 season)
Submission name: towers.cpp
Problem summary
There are A red boxes of height X and B blue boxes of height Y. Build a nonempty vertical tower with alternating colors using any available boxes. Count its distinct possible total heights.
Input
X Y A B.
Output
The number of distinct positive tower heights.
Constraints
1 ≤ X,Y,A,B ≤ 10^9.
Worked example
An independently prepared example for this explanation.
Input
1 2 3 3
Output
9
Solution analysis
- An alternating tower uses either equal counts of the two colors, one extra red box, or one extra blue box. Put S=X+Y and m=min(A,B). Equal counts produce m heights S,2S,…,mS.
- An extra red gives kS+X for 0≤k≤min(B,A−1), and an extra blue gives kS+Y for 0≤k≤min(A,B−1). Each list contains distinct heights. Their residues modulo S separate the equal-count list from both odd-length lists.
- When X≠Y the two odd-length residues also differ, so add all three list sizes. When X=Y the odd lists overlap completely up to the shorter limit: count their union using the larger limit. For X=1,Y=2,A=B=3, all three lists have three heights, giving nine.
Why it works
Alternation forces the stated three count patterns, each of which can be realized. Positive X,Y make each list increasing. Residue comparisons identify exactly all overlaps, so the union formula counts every reachable height once.
Watch out. Count heights, not arrangements. If the box heights are equal, different color count patterns can produce the same height.
Commented C++17 solution
An independently written complete program with standard headers.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
long long x, y, a, b;
cin >> x >> y >> a >> b;
long long pairs = min(a, b);
long long redLimit = min(b, a - 1);
long long blueLimit = min(a, b - 1);
long long answer = pairs;
// Equal heights merge the two odd-length families of tower heights.
if (x == y) {
answer += max(redLimit, blueLimit) + 1;
} else {
answer += redLimit + blueLimit + 2;
}
cout << answer << '\n';
}