L 猪猪车
一些分讨上学习了 题解 的做法。
题意:交互猜四位数。一次询问返回位置和数码完全相同的位数,要求 \(12\) 次询问内猜出答案。
挺有趣的题目。直接记录做法了:
首先询问 \(0000,1111,2222\cdots 8888\),共 \(9\) 次。可以得到当前出现的数字种类数 \(n\) 以及已经出现的数字总数 \(m\)。这样可以省去 \(9999\) 的查询。为了方便,记 \(x\) 表示不可能出现在答案里的数。接下来大力分讨:
\(n = 1\)
记 \(a\) 是出现的那个数字,答案即为 \(aaaa\),平凡。
\(n = 2\)
继续分讨:
- 两种数字各出现 \(2\) 次。记分别为 \(a,b\),那么询问 \(aaxx\),若得到 \(0/2\),答案为 \(aabb\) 或 \(bbaa\)。否则继续询问 \(abxx\) 和 \(xxab\) 以确定前后 \(ab\) 的位置。
- 一种数字出现 \(3\) 次,另一种数字出现 \(1\) 次。记分别为 \(a,b\),询问 \(bxxx\),\(xbxx\),\(xxbx\) 找到 \(b\) 位置即可。
\(n = 3\)
此时一种数字出现 \(2\) 次,另两种 \(1\) 次。记分别为 \(a,b,c\)。询问 \(aaxx\),若得到 \(0/2\),知道两个 \(a\) 都在前/后面就结束了。否则得到 \(1\),前后分别有个 \(a\),再询问 \(bbxx\) 确定 \(b\) 在前面还是后面,最后询问 \(cxxx\) 或 \(xxcx\) 来确定另一侧 \(c\) 的位置。
\(n = 4\)
止步于此了。这应该是本题最关键的地方。
记四个数分别为 \(a,b,c,d\)。第一次询问 \(aabb\),继续分讨:
- 若得到 \(0/2\),相当于确定了 \(a,b\) 在前 / 后,再通过询问 \(ccxx\) 确定 \(c,d\) 在前 / 后。别急。
- 若得到 \(1\),相当于 \(ab\) 是挨在一起的,且在同一侧。再次询问 \(ccxx\) 确定 \(ab\) 是在左侧还是在右侧。
那么现在我们确定了左侧的两个数和右侧的两个数,只需要确定两侧的顺序。记左侧、右侧的两个数分别为 \(f,g\)、\(h,l\)。我们询问 \(fghx\),两侧分开考虑:
- 得到答案为 \(0\)。此时两边顺序都反了,答案为 \(gflh\)。
- 得到答案为 \(1\)。由于左侧的结果只能为 \(0/2\),必定右侧对了。答案为 \(gfhl\)。
- 得到答案为 \(2\)。由于左侧的结果只能为 \(0/2\),必定左侧对了。答案为 \(fglh\)。
那么做完了。
#include <bits/stdc++.h>
#define FstIO ios::sync_with_stdio(0), cin.tie(0)
#define pii pair<ll, ll>
#define pb push_back
#define pbk pop_back
#define mem(a, v) memset(a, v, sizeof a)
#define fi first
#define se second
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
const ll N = 2e6 + 2, M = 22;
const ld eps = 1e-10;
const ll mod = 998244353;
ll t;
ll n, m, x, op, op2;
void Q(ll a, ll b, ll c, ll d) {
cout << "? " << a << b << c << d << '\n';
cout.flush();
}
void oput(ll a, ll b, ll c, ll d) {
cout << "! " << a << b << c << d << '\n';
cout.flush();
}
vector <pii> p;
void solve2() {
ll a = p[0].fi;
ll b = p[1].fi;
if (p[0].se < p[1].se)
swap(a, b);
if (p[0].se == 2) {
Q(a, a, x, x); cin >> op;
if (op == 0) {
oput(b, b, a, a);
return ;
}
if (op == 2) {
oput(a, a, b, b);
return ;
}
Q(a, b, x, x); cin >> op;
Q(x, x, a, b); cin >> op2;
if (!op && !op2)
oput(b, a, b, a);
if (!op && op2)
oput(b, a, a, b);
if (op && !op2)
oput(a, b, b, a);
if (op && op2)
oput(a, b, a, b);
return ;
}
Q(b, x, x, x); cin >> op;
if (op) {
oput(b, a, a, a);
return ;
}
Q(x, b, x, x); cin >> op;
if (op) {
oput(a, b, a, a);
return ;
}
Q(x, x, b, x); cin >> op;
if (op) {
oput(a, a, b, a);
return ;
}
oput(a, a, a, b);
return ;
}
void solve3() {
ll a = p[0].fi;
ll b = p[1].fi;
ll c = p[2].fi;
if (p[1].se == 2) swap(a, b);
if (p[2].se == 2) swap(a, c);
Q(a, a, x, x); cin >> op;
if (op == 0) {
Q(b, x, x, x); cin >> op;
if (op == 0)
oput(c, b, a, a);
else
oput(b, c, a, a);
return ;
}
if (op == 2) {
Q(x, x, b, x); cin >> op;
if (op == 0)
oput(a, a, c, b);
else
oput(a, a, b, c);
return ;
}
// op = 1
Q(b, b, x, x); cin >> op;
if (op == 0) {
Q(a, c, a, x); cin >> op;
if (op == 0) oput(c, a, b, a);
if (op == 1) oput(c, a, a, b);
if (op == 2) oput(a, c, b, a);
if (op == 3) oput(a, c, a, b);
return ;
}
if (op == 1) {
Q(a, b, a, x); cin >> op;
if (op == 0) oput(b, a, c, a);
if (op == 1) oput(b, a, a, c);
if (op == 2) oput(a, b, c, a);
if (op == 3) oput(a, b, a, c);
return ;
}
return ;
}
void solve4() {
ll a = p[0].fi;
ll b = p[1].fi;
ll c = p[2].fi;
ll d = p[3].fi;
ll f, g, h, l;
Q(a, a, b, b); cin >> op;
if (op == 0 || op == 2) {
if (op == 0) {
f = b; h = a;
Q(c, c, d, d); cin >> op;
if (!op) g = d, l = c;
else g = c, l = d;
}
else {
f = a; h = b;
Q(c, c, d, d); cin >> op;
if (!op) g = d, l = c;
else g = c, l = d;
}
}
if (op == 1) {
Q(c, c, x, x); cin >> op;
if (op) {
f = c; g = d; h = a; l = b;
}
else {
f = a; g = b; h = c; l = d;
}
}
Q(f, g, h, x); cin >> op;
if (op == 0) oput(g, f, l, h);
if (op == 1) oput(g, f, h, l);
if (op == 2) oput(f, g, l, h);
if (op == 3) oput(f, g, h, l);
return ;
}
signed main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
FstIO;
cin >> t;
while (t -- ) {
n = m = 0;
p.clear();
for (ll i = 0; i < 9; ++ i ) {
Q(i, i, i, i); cin >> op;
if (!op) {
x = i;
continue;
}
p.pb({i, op});
++ n; m += op;
}
if (m != 4) p.pb({9, 4 - m}), ++ n;
if (n == 1) {
oput(p[0].fi, p[0].fi, p[0].fi, p[0].fi);
continue;
}
if (n == 2) {
solve2();
continue;
}
if (n == 3) {
solve3();
continue;
}
solve4();
}
return 0;
}
浙公网安备 33010602011771号