ICPC 2022 - W. Riddle of the Sphinx
There are three unknown nonnegative integers: the numbers of legs of an axex, a basilisk, and a centaur. We may ask exactly five linear questions of the form ax + by + cz = r, but one of the five answers may be a lie....
Source-first archive entry
This page is built from the copied files in competitive_programming/icpc/2022/W-riddle-of-the-sphinx. Edit
competitive_programming/icpc/2022/W-riddle-of-the-sphinx/solution.tex to update the written solution and
competitive_programming/icpc/2022/W-riddle-of-the-sphinx/solution.cpp to update the implementation.
The website does not replace those files with hand-maintained HTML. It reads the copied source tree during the build and exposes the exact files below.
Problem Statement
Copied statement text kept beside the solution archive for direct reference.
World Finals | ICPC 2023 Luxor
46th Annual hosted by
ICPC World
Championship AASTMT
Problem W
Riddle of the Sphinx
Time limit: 2 seconds
One of the most remarkable landmarks in Egypt is the Great
Sphinx of Giza, a statue depicting a mythical creature with the
head of a human, the body of a lion, and the wings of an eagle.
Sphinxes were regarded as guardians in Egyptian and Greek
mythologies. Probably the most famous sphinx is the one who
guarded the Greek city of Thebes. According to myths, when
Oedipus tried to enter the city, the sphinx gave him the follow-
ing riddle: “Which creature has one voice, but has four feet in
the morning, two feet in the afternoon, and three feet at night?”
As you might have heard, Oedipus correctly answered, “Man
— who crawls on all fours as a baby, then walks on two feet as
an adult, and then uses a walking stick in old age.”
In this problem, you meet a different sphinx who gives you
a somewhat reversed riddle: “How many legs do an axex, a
basilisk, and a centaur have?” While you recognize these as
creatures from Egyptian and Greek mythology, you have no
clue how many legs each has (except that it is a nonnegative
integer). The sphinx sternly instructs you to not touch anything
so you are unable to search for the answer on your phone.
However, the sphinx allows you to ask her five questions. In
each question you can ask the sphinx how many legs some num-
ber of these creatures have in total. For instance, you could ask,
“How many legs do three basilisks and one axex have in to-
tal?” or “How many legs do five centaurs have?” Seems easy Oedipus and the Sphinx by Gustave Moreau, 1864, public domain
enough, you think, but then you remember that sphinxes are
tricky creatures: one of the sphinx’s five answers might be an
outright lie, and you do not know which one.
Write a program to talk to the sphinx, ask the five questions, and solve the riddle.
Interaction
There are exactly five rounds of questions. In each question round, you must first write a line containing
three space-separated integers a, b, and c (0 ≤ a, b, c ≤ 10), representing the question “How many legs
do a axex, b basilisks, and c centaurs have in total?” After the question is asked, an input line containing
a single integer r (0 ≤ r ≤ 105 ) is available on standard input, giving the sphinx’s answer to your
question.
After the five rounds of questions, output a line containing three space-separated nonnegative integers
`a , `b , and `c , indicating the number of legs of an axex, a basilisk, and a centaur, respectively.
46th ICPC World Championship Problem W: Riddle of the Sphinx © ICPC Foundation 15
World Finals | ICPC 2023 Luxor
46th Annual hosted by
ICPC World
Championship AASTMT
Read Sample Interaction 1 Write
1 1 1
12
1 1 1
13
5 0 1
24
1 0 0
4
1 1 0
8
4 4 4
Read Sample Interaction 2 Write
4 4 4
2023
1 0 0
0
0 1 0
42
0 0 1
2024
0 0 0
0
0 42 2024
46th ICPC World Championship Problem W: Riddle of the Sphinx © ICPC Foundation 16
Editorial
Rendered from the copied solution.tex file. The original TeX source remains
available below.
Key Observations
Each question gives one linear equation in the three unknowns.
If we choose five query vectors such that any three of them are linearly independent, then after discarding the one lie the remaining truthful answers determine a unique solution.
A convenient fixed choice is \[ (1,0,0),\ (0,1,0),\ (0,0,1),\ (1,1,1),\ (1,2,3). \] Any three of these rows have nonzero determinant.
Therefore, for each candidate lie position we can solve a $3 \times 3$ system and then verify the resulting triple against the four answers assumed to be truthful.
Algorithm
Ask the five fixed questions above and read the five answers.
For each index $i$, pretend the $i$th answer is the lie.
Solve the linear system from any three of the other four equations with Cramer's rule.
Reject the candidate if the system is singular, if any coordinate is negative, or if any of the four supposedly truthful equations is violated.
Output the unique candidate that survives.
Correctness Proof
We prove that the algorithm returns the correct answer.
Lemma 1.
For the chosen five query vectors, any three are linearly independent.
Proof.
This is a direct determinant check. The first three rows are the identity matrix. Any triple containing at least two of them is obviously independent, and the remaining mixed triples with $(1,1,1)$ and $(1,2,3)$ also have nonzero determinant. Hence every triple is independent. □
Lemma 2.
If we discard the actual lie, the algorithm reconstructs the true values $(x,y,z)$.
Proof.
After removing the lie, the remaining four equations are all truthful. By Lemma 1, any three of their row vectors are independent, so the corresponding $3 \times 3$ system has a unique solution. The true triple satisfies those equations, so uniqueness implies that the solved triple is exactly the true one. It also passes the verification against all four truthful equations. □
Theorem.
The algorithm outputs the correct answer for every valid input.
Proof.
By Lemma 2, when the algorithm guesses the actual lie position, it keeps the true triple. Now consider any wrong lie position. Then at least one lie remains among the four equations checked during verification, so the candidate cannot satisfy all four unless that ``lie'' happens to match the truthful value, which would mean it was not a lie at all. Therefore every wrong guess is rejected, and the only surviving output is the true triple. □
Complexity Analysis
The number of questions and candidate lie positions is constant. The running time is $O(1)$ and the memory usage is $O(1)$.
Implementation Notes
Because this is interactive, each question must be flushed immediately after printing. The implementation uses
endl.All arithmetic easily fits in 64-bit signed integers.
Code
Exact copied C++ implementation from solution.cpp.
#include <bits/stdc++.h>
using namespace std;
namespace {
long long det3(const array<array<long long, 3>, 3>& a) {
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) -
a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) +
a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
}
bool solve_system(const vector<array<long long, 3>>& rows, const vector<long long>& rhs,
array<long long, 3>& answer) {
array<array<long long, 3>, 3> a{};
for (int i = 0; i < 3; ++i) {
a[i] = rows[i];
}
long long det = det3(a);
if (det == 0) {
return false;
}
for (int col = 0; col < 3; ++col) {
auto b = a;
for (int row = 0; row < 3; ++row) {
b[row][col] = rhs[row];
}
long long num = det3(b);
if (num % det != 0) {
return false;
}
answer[col] = num / det;
}
return true;
}
void solve() {
const vector<array<long long, 3>> queries = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
{1, 1, 1},
{1, 2, 3},
};
vector<long long> responses(5);
for (int i = 0; i < 5; ++i) {
cout << queries[i][0] << ' ' << queries[i][1] << ' ' << queries[i][2] << endl;
cin >> responses[i];
}
for (int lie = 0; lie < 5; ++lie) {
vector<array<long long, 3>> rows;
vector<long long> rhs;
for (int i = 0; i < 5; ++i) {
if (i == lie) {
continue;
}
rows.push_back(queries[i]);
rhs.push_back(responses[i]);
}
array<long long, 3> answer{};
if (!solve_system(rows, rhs, answer)) {
continue;
}
if (answer[0] < 0 || answer[1] < 0 || answer[2] < 0) {
continue;
}
bool ok = true;
for (int i = 0; i < 5; ++i) {
if (i == lie) {
continue;
}
long long value = 0;
for (int j = 0; j < 3; ++j) {
value += queries[i][j] * answer[j];
}
if (value != responses[i]) {
ok = false;
break;
}
}
if (ok) {
cout << answer[0] << ' ' << answer[1] << ' ' << answer[2] << endl;
return;
}
}
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
Source Files
Exact copied source-of-truth files. Edit solution.tex for the write-up and solution.cpp for the implementation.
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amssymb,amsthm}
\usepackage{enumitem}
\title{ICPC World Finals 2022\\W. Riddle of the Sphinx}
\author{}
\date{}
\begin{document}
\maketitle
\section*{Problem Summary}
There are three unknown nonnegative integers: the numbers of legs of an axex, a basilisk, and a
centaur. We may ask exactly five linear questions of the form
\[
ax + by + cz = r,
\]
but one of the five answers may be a lie. We must still determine the unique triple $(x,y,z)$.
\section*{Key Observations}
\begin{itemize}[leftmargin=*]
\item Each question gives one linear equation in the three unknowns.
\item If we choose five query vectors such that \emph{any} three of them are linearly independent, then
after discarding the one lie the remaining truthful answers determine a unique solution.
\item A convenient fixed choice is
\[
(1,0,0),\ (0,1,0),\ (0,0,1),\ (1,1,1),\ (1,2,3).
\]
Any three of these rows have nonzero determinant.
\item Therefore, for each candidate lie position we can solve a $3 \times 3$ system and then verify the
resulting triple against the four answers assumed to be truthful.
\end{itemize}
\section*{Algorithm}
\begin{enumerate}[leftmargin=*]
\item Ask the five fixed questions above and read the five answers.
\item For each index $i$, pretend the $i$th answer is the lie.
\item Solve the linear system from any three of the other four equations with Cramer's rule.
\item Reject the candidate if the system is singular, if any coordinate is negative, or if any of the four
supposedly truthful equations is violated.
\item Output the unique candidate that survives.
\end{enumerate}
\section*{Correctness Proof}
We prove that the algorithm returns the correct answer.
\paragraph{Lemma 1.}
For the chosen five query vectors, any three are linearly independent.
\paragraph{Proof.}
This is a direct determinant check. The first three rows are the identity matrix. Any triple containing at
least two of them is obviously independent, and the remaining mixed triples with $(1,1,1)$ and
$(1,2,3)$ also have nonzero determinant. Hence every triple is independent. \qed
\paragraph{Lemma 2.}
If we discard the actual lie, the algorithm reconstructs the true values $(x,y,z)$.
\paragraph{Proof.}
After removing the lie, the remaining four equations are all truthful. By Lemma 1, any three of their row
vectors are independent, so the corresponding $3 \times 3$ system has a unique solution. The true triple
satisfies those equations, so uniqueness implies that the solved triple is exactly the true one. It also
passes the verification against all four truthful equations. \qed
\paragraph{Theorem.}
The algorithm outputs the correct answer for every valid input.
\paragraph{Proof.}
By Lemma 2, when the algorithm guesses the actual lie position, it keeps the true triple. Now consider any
wrong lie position. Then at least one lie remains among the four equations checked during verification, so
the candidate cannot satisfy all four unless that ``lie'' happens to match the truthful value, which would
mean it was not a lie at all. Therefore every wrong guess is rejected, and the only surviving output is the
true triple. \qed
\section*{Complexity Analysis}
The number of questions and candidate lie positions is constant. The running time is $O(1)$ and the
memory usage is $O(1)$.
\section*{Implementation Notes}
\begin{itemize}[leftmargin=*]
\item Because this is interactive, each question must be flushed immediately after printing. The
implementation uses \texttt{endl}.
\item All arithmetic easily fits in 64-bit signed integers.
\end{itemize}
\end{document}
#include <bits/stdc++.h>
using namespace std;
namespace {
long long det3(const array<array<long long, 3>, 3>& a) {
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) -
a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) +
a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
}
bool solve_system(const vector<array<long long, 3>>& rows, const vector<long long>& rhs,
array<long long, 3>& answer) {
array<array<long long, 3>, 3> a{};
for (int i = 0; i < 3; ++i) {
a[i] = rows[i];
}
long long det = det3(a);
if (det == 0) {
return false;
}
for (int col = 0; col < 3; ++col) {
auto b = a;
for (int row = 0; row < 3; ++row) {
b[row][col] = rhs[row];
}
long long num = det3(b);
if (num % det != 0) {
return false;
}
answer[col] = num / det;
}
return true;
}
void solve() {
const vector<array<long long, 3>> queries = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
{1, 1, 1},
{1, 2, 3},
};
vector<long long> responses(5);
for (int i = 0; i < 5; ++i) {
cout << queries[i][0] << ' ' << queries[i][1] << ' ' << queries[i][2] << endl;
cin >> responses[i];
}
for (int lie = 0; lie < 5; ++lie) {
vector<array<long long, 3>> rows;
vector<long long> rhs;
for (int i = 0; i < 5; ++i) {
if (i == lie) {
continue;
}
rows.push_back(queries[i]);
rhs.push_back(responses[i]);
}
array<long long, 3> answer{};
if (!solve_system(rows, rhs, answer)) {
continue;
}
if (answer[0] < 0 || answer[1] < 0 || answer[2] < 0) {
continue;
}
bool ok = true;
for (int i = 0; i < 5; ++i) {
if (i == lie) {
continue;
}
long long value = 0;
for (int j = 0; j < 3; ++j) {
value += queries[i][j] * answer[j];
}
if (value != responses[i]) {
ok = false;
break;
}
}
if (ok) {
cout << answer[0] << ' ' << answer[1] << ' ' << answer[2] << endl;
return;
}
}
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}