L 猪猪车

CCPC2026 黑龙江 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; 
}
posted @ 2026-07-30 19:30  RainyRadio  阅读(2)  评论(0)    收藏  举报