#include <algorithm>
#include <cstdio>
#include <vector>
#include <lpsolve/lp_lib.h>
using namespace std;
// the 21 candidates for the answer, encoded into bits
const int CC = 21;
const int candidates[CC] = { 57, 89, 99, 101, 105, 113, 135, 139, 141, 147, 149, 153, 163, 165, 169, 177, 195, 197, 201, 209, 225 };
void initialize_LP(lprec** LP) {
*LP = make_lp(0,8); // 0 rows so far, 8 variables
set_verbose(*LP, IMPORTANT); // shut up when solving
double coef[2]={-1.,+1.}; // add the constraints of the form w[i]+1 <= w[i+1]
int vars[2];
for (int i=1; i<=7; ++i) {
vars[0]=i; vars[1]=i+1;
add_constraintex(*LP,2,coef,vars,GE,1);
}
coef[0]=1; vars[0]=8; // add the objective function
set_obj_fnex(*LP,1,coef,vars);
}
void add_answer(lprec** LP, int lighter_set) {
// add the constraint that some set of bags is lighter than its complement
int heavier_set = 255 ^ lighter_set;
double coef[9];
for (int i=0; i<8; ++i) if (heavier_set & 1<<i) coef[i+1] = +1.;
for (int i=0; i<8; ++i) if (lighter_set & 1<<i) coef[i+1] = -1.;
add_constraint(*LP,coef,GE,1);
}
void add_question(lprec** LP, int left_set) {
// add the constraint that some set of bags exactly as heavy as its complement
int right_set = 255 ^ left_set;
double coef[9];
for (int i=0; i<8; ++i) if (right_set & 1<<i) coef[i+1] = +1.;
for (int i=0; i<8; ++i) if (left_set & 1<<i) coef[i+1] = -1.;
add_constraint(*LP,coef,EQ,0);
}
bool solvable(int limit, const vector<int> lighter_sets) {
// <lighter_sets> contains the lighter set for each measurement we already did
// <solve> returns true iff we can guarantee a win within <limit> additional questions
vector<int> alive;
for (int c=0; c<CC; ++c) {
lprec *LP;
initialize_LP(&LP);
for (int ls:lighter_sets) add_answer(&LP,ls);
add_question(&LP,candidates[c]);
if (!solve(LP)) alive.push_back( candidates[c] ); // solve() returns 0 iff a solution was found
delete_lp(LP);
}
if (int(alive.size()) <= 1) return true;
// if (limit == 0) return 1234567; // multiple options && no questions left
if (int(alive.size()) > (1<<(limit+1))-1 ) return false; // too many candidates, too few questions
for (int q:alive) {
vector<int> first = lighter_sets; first.push_back(q);
vector<int> second = lighter_sets; second.push_back(255^q);
if (solvable(limit-1,first) && solvable(limit-1,second)) return true;
}
return false;
}
int main() {
for (int q=1; ; ++q) {
printf("%d questions: ",q); fflush(stdout);
bool s = solvable(q,vector<int>());
printf("%ssolvable\n",s?"":"not ");
if (s) break;
}
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGxwc29sdmUvbHBfbGliLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyB0aGUgMjEgY2FuZGlkYXRlcyBmb3IgdGhlIGFuc3dlciwgZW5jb2RlZCBpbnRvIGJpdHMKY29uc3QgaW50IENDID0gMjE7CmNvbnN0IGludCBjYW5kaWRhdGVzW0NDXSA9IHsgNTcsIDg5LCA5OSwgMTAxLCAxMDUsIDExMywgMTM1LCAxMzksIDE0MSwgMTQ3LCAxNDksIDE1MywgMTYzLCAxNjUsIDE2OSwgMTc3LCAxOTUsIDE5NywgMjAxLCAyMDksIDIyNSB9OwoKdm9pZCBpbml0aWFsaXplX0xQKGxwcmVjKiogTFApIHsKICAgICpMUCA9IG1ha2VfbHAoMCw4KTsgICAgICAgICAgICAgLy8gMCByb3dzIHNvIGZhciwgOCB2YXJpYWJsZXMKICAgIHNldF92ZXJib3NlKCpMUCwgSU1QT1JUQU5UKTsgICAgLy8gc2h1dCB1cCB3aGVuIHNvbHZpbmcKICAgIGRvdWJsZSBjb2VmWzJdPXstMS4sKzEufTsgICAgICAgLy8gYWRkIHRoZSBjb25zdHJhaW50cyBvZiB0aGUgZm9ybSB3W2ldKzEgPD0gd1tpKzFdCiAgICBpbnQgdmFyc1syXTsKICAgIGZvciAoaW50IGk9MTsgaTw9NzsgKytpKSB7ICAgICAgCiAgICAgICAgdmFyc1swXT1pOyB2YXJzWzFdPWkrMTsgCiAgICAgICAgYWRkX2NvbnN0cmFpbnRleCgqTFAsMixjb2VmLHZhcnMsR0UsMSk7IAogICAgfQogICAgY29lZlswXT0xOyB2YXJzWzBdPTg7ICAgICAgICAgICAvLyBhZGQgdGhlIG9iamVjdGl2ZSBmdW5jdGlvbgogICAgc2V0X29ial9mbmV4KCpMUCwxLGNvZWYsdmFycyk7IAp9Cgp2b2lkIGFkZF9hbnN3ZXIobHByZWMqKiBMUCwgaW50IGxpZ2h0ZXJfc2V0KSB7CiAgICAvLyBhZGQgdGhlIGNvbnN0cmFpbnQgdGhhdCBzb21lIHNldCBvZiBiYWdzIGlzIGxpZ2h0ZXIgdGhhbiBpdHMgY29tcGxlbWVudAogICAgaW50IGhlYXZpZXJfc2V0ID0gMjU1IF4gbGlnaHRlcl9zZXQ7CiAgICBkb3VibGUgY29lZls5XTsKICAgIGZvciAoaW50IGk9MDsgaTw4OyArK2kpIGlmIChoZWF2aWVyX3NldCAmIDE8PGkpIGNvZWZbaSsxXSA9ICsxLjsKICAgIGZvciAoaW50IGk9MDsgaTw4OyArK2kpIGlmIChsaWdodGVyX3NldCAmIDE8PGkpIGNvZWZbaSsxXSA9IC0xLjsKICAgIGFkZF9jb25zdHJhaW50KCpMUCxjb2VmLEdFLDEpOwp9Cgp2b2lkIGFkZF9xdWVzdGlvbihscHJlYyoqIExQLCBpbnQgbGVmdF9zZXQpIHsKICAgIC8vIGFkZCB0aGUgY29uc3RyYWludCB0aGF0IHNvbWUgc2V0IG9mIGJhZ3MgZXhhY3RseSBhcyBoZWF2eSBhcyBpdHMgY29tcGxlbWVudAogICAgaW50IHJpZ2h0X3NldCA9IDI1NSBeIGxlZnRfc2V0OwogICAgZG91YmxlIGNvZWZbOV07CiAgICBmb3IgKGludCBpPTA7IGk8ODsgKytpKSBpZiAocmlnaHRfc2V0ICYgMTw8aSkgY29lZltpKzFdID0gKzEuOwogICAgZm9yIChpbnQgaT0wOyBpPDg7ICsraSkgaWYgKGxlZnRfc2V0ICAmIDE8PGkpIGNvZWZbaSsxXSA9IC0xLjsKICAgIGFkZF9jb25zdHJhaW50KCpMUCxjb2VmLEVRLDApOwp9Cgpib29sIHNvbHZhYmxlKGludCBsaW1pdCwgY29uc3QgdmVjdG9yPGludD4gbGlnaHRlcl9zZXRzKSB7CiAgICAvLyA8bGlnaHRlcl9zZXRzPiBjb250YWlucyB0aGUgbGlnaHRlciBzZXQgZm9yIGVhY2ggbWVhc3VyZW1lbnQgd2UgYWxyZWFkeSBkaWQKICAgIC8vIDxzb2x2ZT4gcmV0dXJucyB0cnVlIGlmZiB3ZSBjYW4gZ3VhcmFudGVlIGEgd2luIHdpdGhpbiA8bGltaXQ+IGFkZGl0aW9uYWwgcXVlc3Rpb25zCiAgICB2ZWN0b3I8aW50PiBhbGl2ZTsKICAgIGZvciAoaW50IGM9MDsgYzxDQzsgKytjKSB7CiAgICAgICAgbHByZWMgKkxQOwogICAgICAgIGluaXRpYWxpemVfTFAoJkxQKTsKICAgICAgICBmb3IgKGludCBsczpsaWdodGVyX3NldHMpIGFkZF9hbnN3ZXIoJkxQLGxzKTsKICAgICAgICBhZGRfcXVlc3Rpb24oJkxQLGNhbmRpZGF0ZXNbY10pOwogICAgICAgIGlmICghc29sdmUoTFApKSBhbGl2ZS5wdXNoX2JhY2soIGNhbmRpZGF0ZXNbY10gKTsgLy8gc29sdmUoKSByZXR1cm5zIDAgaWZmIGEgc29sdXRpb24gd2FzIGZvdW5kCiAgICAgICAgZGVsZXRlX2xwKExQKTsKICAgIH0KICAgIGlmIChpbnQoYWxpdmUuc2l6ZSgpKSA8PSAxKSByZXR1cm4gdHJ1ZTsKICAgIC8vIGlmIChsaW1pdCA9PSAwKSByZXR1cm4gMTIzNDU2NzsgLy8gbXVsdGlwbGUgb3B0aW9ucyAmJiBubyBxdWVzdGlvbnMgbGVmdAogICAgaWYgKGludChhbGl2ZS5zaXplKCkpID4gKDE8PChsaW1pdCsxKSktMSApIHJldHVybiBmYWxzZTsgLy8gdG9vIG1hbnkgY2FuZGlkYXRlcywgdG9vIGZldyBxdWVzdGlvbnMKCiAgICBmb3IgKGludCBxOmFsaXZlKSB7CiAgICAgICAgdmVjdG9yPGludD4gZmlyc3QgID0gbGlnaHRlcl9zZXRzOyBmaXJzdC5wdXNoX2JhY2socSk7IAogICAgICAgIHZlY3RvcjxpbnQ+IHNlY29uZCA9IGxpZ2h0ZXJfc2V0czsgc2Vjb25kLnB1c2hfYmFjaygyNTVecSk7IAogICAgICAgIGlmIChzb2x2YWJsZShsaW1pdC0xLGZpcnN0KSAmJiBzb2x2YWJsZShsaW1pdC0xLHNlY29uZCkpIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9CgppbnQgbWFpbigpIHsKICAgIGZvciAoaW50IHE9MTsgOyArK3EpIHsKICAgICAgICBwcmludGYoIiVkIHF1ZXN0aW9uczogIixxKTsgZmZsdXNoKHN0ZG91dCk7CiAgICAgICAgYm9vbCBzID0gc29sdmFibGUocSx2ZWN0b3I8aW50PigpKTsKICAgICAgICBwcmludGYoIiVzc29sdmFibGVcbiIscz8iIjoibm90ICIpOwogICAgICAgIGlmIChzKSBicmVhazsKICAgIH0KfQ==