Problem: icpc2022_world_finals_a
Difficulty: medium
Categories: math
Time limit: 2000 ms, memory limit: 256 MB

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 following 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 number of these creatures have in total. For instance, you could ask, “How many legs do three basilisks and one axex have in total?” or “How many legs do five centaurs have?” Seems easy 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.

![](images/70bb1228c86ed7c8a26393a2cc782f0605d76f83447f9ee3fbfd3b8472bd2c9f.jpg)  
Oedipus and the Sphinx by Gustave Moreau,1864,public domain

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 \left( 0 \leq a , b , c \leq 1 0 \right)$ , 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 \leq r \leq 1 0 ^ { 5 }$ ） 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 $\ell _ { a } , \ell _ { b }$ ,and $\ell _ { c }$ , indicating the number of legs of an axex,a basilisk,and a centaur, respectively.

# Read

# Sample Interaction 1

Write

<table><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>111</td></tr><tr><td rowspan=1 colspan=1>12</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>111</td></tr><tr><td rowspan=1 colspan=1>13</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>501</td></tr><tr><td rowspan=1 colspan=1>24</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>100</td></tr><tr><td rowspan=1 colspan=1>4</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>110</td></tr><tr><td rowspan=1 colspan=1>8</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=1>444</td></tr></table>

Read

# Sample Interaction 2

Write

<table><tr><td rowspan=1 colspan=2>444</td></tr><tr><td rowspan=1 colspan=2>2023</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=2>100</td></tr><tr><td rowspan=1 colspan=2>0</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=2>010</td></tr><tr><td rowspan=1 colspan=2>42</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=2>001</td></tr><tr><td rowspan=1 colspan=2>2024</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=2>000</td></tr><tr><td rowspan=1 colspan=2>0</td><td rowspan=1 colspan=1></td></tr><tr><td rowspan=1 colspan=1></td><td rowspan=1 colspan=2>042 2024</td></tr></table>

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;


static long long queries = 0;
static long long query_limit = 5;


static long long La, Lb, Lc;
static int lie_idx; 



static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}


static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

int main(int argc, char* argv[]) {
    
    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    
    string mode = inf.readToken();
    if (mode != "fixed") {
        finish(_fail, "Interactor input mismatch: expected 'fixed' mode.");
    }
    La = inf.readLong();
    Lb = inf.readLong();
    Lc = inf.readLong();
    lie_idx = inf.readInt();

    
    
    int hard_cap = 50; 

    while (true) {
        
        if (cin.eof()) {
            finish(_pe, "Unexpected end of input (expected query or answer)");
        }

        string token;
        cin >> token;
        
        if (cin.fail()) {
            if (cin.eof()) finish(_pe, "Unexpected end of input");
            finish(_pe, "Failed to read token");
        }

        bool is_answer = false;
        bool is_query = false;
        long long a = -1, b = -1, c = -1;

        
        if (token == "!") {
            is_answer = true;
            if (!(cin >> a >> b >> c)) finish(_pe, "Expected 3 integers after '!'");
        } else if (token == "?") {
            is_query = true;
            if (!(cin >> a >> b >> c)) finish(_pe, "Expected 3 integers after '?'");
        } else {
            
            try {
                size_t idx;
                a = stoll(token, &idx);
                if (idx != token.size()) finish(_pe, "Invalid token (expected integer, '?', or '!')");
            } catch (...) {
                finish(_pe, "Invalid token format");
            }
            if (!(cin >> b >> c)) finish(_pe, "Expected 3 integers");

            
            
            if (queries < 5) {
                is_query = true;
            } else {
                is_answer = true;
            }
        }

        if (is_answer) {
            if (a == La && b == Lb && c == Lc) {
                finish(_ok, "Correct answer");
            } else {
                string msg = "Wrong answer. Expected: " + to_string(La) + " " + to_string(Lb) + " " + to_string(Lc)
                           + ", Found: " + to_string(a) + " " + to_string(b) + " " + to_string(c);
                finish(_wa, msg);
            }
        } else {
            
            if (queries >= 5) {
                finish(_wa, "Too many queries used (limit is 5)");
            }

            if (a < 0 || a > 10 || b < 0 || b > 10 || c < 0 || c > 10) {
                finish(_pe, "Query coefficients must be between 0 and 10");
            }

            long long response = a * La + b * Lb + c * Lc;

            
            
            if (queries + 1 == lie_idx) {
                
                
                
                if (response == 0) response = 1;
                else response = response - 1;
            }

            cout << response << endl; 
            queries++;
            
            
            log_metrics();

            if (queries > hard_cap) {
                finish(_pe, "Hard query limit exceeded (infinite loop)");
            }
        }
    }

    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <random>

using namespace std;


static long long queries_count = 0;
static long long query_limit = 5;


void log_metrics() {
    try {
        tout << "queries=" << queries_count << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}


void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}


struct Candidate {
    int a, b, c;
    int errors; 
};


vector<Candidate> pool;
struct History {
    int a, b, c;
    long long r;
};
vector<History> history_log;


bool adaptive_mode = false;
int fix_a, fix_b, fix_c;
int fix_lie_idx; 


long long eval_query(int a, int b, int c, int la, int lb, int lc) {
    return 1LL * a * la + 1LL * b * lb + 1LL * c * lc;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics); 

    
    
    string mode_str = inf.readToken();
    if (mode_str == "fixed") {
        adaptive_mode = false;
        fix_a = inf.readInt();
        fix_b = inf.readInt();
        fix_c = inf.readInt();
        fix_lie_idx = inf.readInt();
    } else {
        adaptive_mode = true;
        int seed = inf.readInt();
        rnd.setSeed(seed);
        
        
        auto add = [&](int a, int b, int c) {
            pool.push_back({a, b, c, 0});
        };
        
        
        add(0, 0, 0);
        
        
        vector<int> corners = {0, 1, 2, 3, 5, 10, 100, 1000, 10000, 20000};
        for(int x : corners) for(int y : corners) for(int z : corners) add(x,y,z);
        
        
        
        while(pool.size() < 60000) {
            int t = rnd.next(3);
            if(t == 0) {
                
                add(rnd.next(0, 20), rnd.next(0, 20), rnd.next(0, 20));
            } else if (t == 1) {
                
                add(rnd.next(0, 500), rnd.next(0, 500), rnd.next(0, 500));
            } else {
                
                add(rnd.next(0, 20000), rnd.next(0, 20000), rnd.next(0, 20000));
            }
        }
    }

    
    for (int round = 1; round <= 5; round++) {
        
        if (cin.eof()) finish(_pe, "Unexpected EOF in query loop");
        
        int qa, qb, qc;
        if (!(cin >> qa >> qb >> qc)) finish(_pe, "Invalid query format");
        
        
        if (qa < 0 || qa > 10 || qb < 0 || qb > 10 || qc < 0 || qc > 10) {
            finish(_pe, "Coefficients must be in range [0, 10]");
        }
        
        queries_count++;
        
        if (queries_count == 1) log_metrics();

        long long reply = 0;
        
        if (!adaptive_mode) {
            
            long long val = eval_query(qa, qb, qc, fix_a, fix_b, fix_c);
            if (round == fix_lie_idx) {
                reply = val + 1; 
            } else {
                reply = val;
            }
        } else {
            
            
            static vector<pair<long long, int>> votes;
            votes.clear();
            if (votes.capacity() < pool.size()) votes.reserve(pool.size());
            
            for(int i=0; i<(int)pool.size(); ++i) {
                votes.push_back({eval_query(qa, qb, qc, pool[i].a, pool[i].b, pool[i].c), i});
            }
            sort(votes.begin(), votes.end());
            
            long long best_r = 0;
            pair<int, int> best_score = {-1, -1}; 
            
            if (!votes.empty()) {
                int n = votes.size();
                for(int i=0; i<n; ) {
                    int j = i;
                    long long current_val = votes[i].first;
                    int count_err1 = 0;
                    int count_err0 = 0;
                    
                    
                    while(j < n && votes[j].first == current_val) {
                        int idx = votes[j].second;
                        if (pool[idx].errors == 1) count_err1++;
                        if (pool[idx].errors == 0) count_err0++;
                        j++;
                    }
                    
                    
                    
                    if (make_pair(count_err1, count_err0) > best_score) {
                        best_score = {count_err1, count_err0};
                        best_r = current_val;
                    }
                    i = j;
                }
            }
            
            reply = best_r;
            
            
            
            int w = 0;
            for(int k=0; k<(int)pool.size(); ++k) {
                long long v = eval_query(qa, qb, qc, pool[k].a, pool[k].b, pool[k].c);
                int cost = (v != reply ? 1 : 0);
                pool[k].errors += cost;
                if (pool[k].errors <= 1) {
                    pool[w++] = pool[k];
                }
            }
            pool.resize(w);
        }
        
        cout << reply << endl;
        history_log.push_back({qa, qb, qc, reply});
    }

    
    int la, lb, lc;
    if (!(cin >> la >> lb >> lc)) finish(_pe, "Expected final answer (3 integers)");
    
    
    int mismatches = 0;
    for(const auto& h : history_log) {
        if (eval_query(h.a, h.b, h.c, la, lb, lc) != h.r) {
            mismatches++;
        }
    }
    
    if (mismatches > 1) {
        finish(_wa, "Final answer is inconsistent with query history (more than 1 mismatch)");
    }
    
    if (adaptive_mode) {
        
        for(const auto& c : pool) {
            
            if (c.a != la || c.b != lb || c.c != lc) {
                finish(_wa, "Solution is not unique; another valid configuration exists");
            }
        }
    } else {
        
        if (la != fix_a || lb != fix_b || lc != fix_c) {
            finish(_wa, "Incorrect answer for fixed test case");
        }
    }

    finish(_ok, "Correct");
    return 0;
}


Test generator (C++):









#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");

    if (mode == "non") {
        
        
        
        

        cout << "fixed" << endl;

        
        
        
        
        int sum_limit = 10000;
        
        int la, lb, lc;
        
        
        int type = rnd.next(100);
        
        if (type < 5) {
            
            la = 0; lb = 0; lc = 0;
        } else if (type < 10) {
            
            la = 3333; lb = 3333; lc = 3333;
        } else if (type < 20) {
            
            int val = rnd.next(0, sum_limit);
            int who = rnd.next(3);
            la = (who == 0 ? val : 0);
            lb = (who == 1 ? val : 0);
            lc = (who == 2 ? val : 0);
        } else if (type < 30) {
            
            int s = rnd.next(0, sum_limit);
            auto p = rnd.partition(2, (long long)s);
            int who = rnd.next(3); 
            if (who == 0) { la = 0; lb = (int)p[0]; lc = (int)p[1]; }
            else if (who == 1) { la = (int)p[0]; lb = 0; lc = (int)p[1]; }
            else { la = (int)p[0]; lb = (int)p[1]; lc = 0; }
        } else {
            
            int s = rnd.next(0, sum_limit);
            auto p = rnd.partition(3, (long long)s);
            
            shuffle(p.begin(), p.end());
            la = (int)p[0];
            lb = (int)p[1];
            lc = (int)p[2];
        }
        
        cout << la << " " << lb << " " << lc << endl;

        
        
        int lie_idx;
        if (rnd.next(20) == 0) { 
            lie_idx = 0;
        } else {
            lie_idx = rnd.next(1, 5);
        }
        cout << lie_idx << endl;

    } else if (mode == "adp") {
        
        
        

        cout << "adaptive" << endl;
        
        cout << rnd.next(1, 2000000000) << endl;

    } else {
        quitf(_fail, "Unknown mode: %s", mode.c_str());
    }

    return 0;
}