CF #812 (Div. 2) D

题意:

交互题,首先给定2^n个人,相邻两个人比赛,输的推出,不断重复这个过程直到只剩最后一个胜者。输出这个胜者。每次可以询问两个人的胜场数比较状态,例如询问1号和2号,若1号胜利的多则返回1,2胜的多则返回2,平手为0。最大询问此数为

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        (2^{n}+2)/3

思路: 

首先,如果我们不断的两两询问,显然是一定能得到答案的,但是这样询问的询问此数是:        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        2^{n/2+1}-1   

(等比级数求和,首相为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;
}

 

<div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"><p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p><div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"><video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video></div><table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody></table><p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p><p> </p><p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p></div>
06-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值