题意:
交互题,首先给定2^n个人,相邻两个人比赛,输的推出,不断重复这个过程直到只剩最后一个胜者。输出这个胜者。每次可以询问两个人的胜场数比较状态,例如询问1号和2号,若1号胜利的多则返回1,2胜的多则返回2,平手为0。最大询问此数为
思路:
首先,如果我们不断的两两询问,显然是一定能得到答案的,但是这样询问的询问此数是:
(等比级数求和,首相为1,末项为2^n/2,公比为2)这显然是不能过的,但是,如果能每两次询问得到四个人的比试结果,即每次减少四分之一的人,则询问此数可行。具体的:
不难发现,无论如何改变胜利的人的编号,所有人的胜场状态一定是0012,利用这一点可以在两次内询问出来
首先询问1和3
若1多,则1可能胜1场也可能胜两场,此时只需要再比1和4即可。
若3多,则与上同。
若平手,则说明他们的胜场均为0,此时再比2和4就能得到答案。
解决。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9 + 9;
const ll INF = 1e18l;
/*
priority_queue<int> big_heep;
priority_queue<int,vector<int>,greater<int> > small_heep;
struct cmp{//if return true,it means that the number in the left was smaller than the right one
bool operator () (int a,int b){
}
};
*/
int n;
vector<int> a;
int ask(int x, int y) {
int t;
cout << "? " << x << " " << y << "\n";
cout.flush();
cin >> t;
return t;
}
void work() {
a.clear();
cin >> n;
for (int i = 1; i <= (1 << n); i++) a.push_back(i);
while (a.size() > 1) {
vector<int> b;
if (a.size() == 2) {
int q = ask(a[0], a[1]);
int x = 0;
if (q == 1) {
x = a[0];
a.clear();
a.push_back(x);
}
else {
x = a[1];
a.clear();
a.push_back(x);
}
break;
}
for (int i = 0; i < a.size(); i += 4) {
int flag1 = a[i], flag2 = a[i + 1], flag3 = a[i + 2], flag4 = a[i + 3];
int q = ask(flag1, flag3);
if (q == 1){
int v = ask(flag1, flag4);
if (v == 1) b.push_back(flag1);
else b.push_back(flag4);
}
else if (q == 2){
int v = ask(flag2, flag3);
if (v == 1)b.push_back(flag2);
else b.push_back(flag3);
}
else if (q==0){
int v = ask(flag2, flag4);
if (v == 1) b.push_back(flag2);
else b.push_back(flag4);
}
}
a = b;
}
cout << "! " << a[0] << "\n";
cout.flush();
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t;
cin >> t;
while (t--) {
work();
}
return 0;
}