D. Bit Guessing Game(单独询问某一位上是否有一)

文章描述了一个在Codeforces平台上关于交互式问题的编程挑战。Hayato需要猜出Kira隐藏的正整数n,初始信息是二进制表示中单位比特的数量cnt。Hayato每次可以选择一个整数尝试从n中减去,但不能超过30次操作且不能减去大于n的数。最终目标是在不超过限制次数内猜出原始的n值。
摘要由CSDN通过智能技术生成

Problem - D - Codeforces

这是一个互动的问题。Kira有一个隐藏的正整数n, hayyato需要猜出来。最初,Kira给Hayato的值是cnt——二进制表示n的单位比特数。要猜出n, Hayato只能做一种操作:选择一个整数,然后用n减去它。注意,每次操作后,数字n都会发生变化。吉良不喜欢糟糕的请求,所以如果隼人试图减去一个大于n的数字,他就会输给吉良。在每次操作之后,Kira将更新后的值cnt(更新后的值n的二进制表示中的单位比特数)给Hayato。Kira没有太多耐心,所以hayyato必须在不超过30次的操作后猜测n的原始值。因为hayyato在上小学,他请求你的帮助。写一个程序来猜测数字n。基拉是一个诚实的人,所以他在所有操作之前都选择初始数字n,之后不改变它。输入输入数据包含几个测试用例。第一行包含一个整数t (1 t <500)测试用例的数量。测试用例的描述如下。每个测试用例的第一行包含数字cnt——二进制表示的单位位的初始数目n。隐藏整数n满足以下约束:1 < n < 109。交互要猜出n,最多可以执行30次操作。要做到这一点,打印一行以下格式:"- x" (1 < x < 10°)。在这个操作之后,n减去z,因此n改变了。如果数字z大于当前值n,则认为请求无效。操作结束后,读取包含单个非负整数cnt的一行——操作结束后,当前n的二进制表示的单位比特数。当你知道n的初始值时,打印一行,格式如下:"!N " (1 < N < 10°)。在此之后,继续进行下一个测试用例,如果没有测试用例,则终止程序。如果您的程序对一个测试用例执行了超过30个操作,减去了一个大于n的数字z,或者发出了一个错误的请求,那么对请求的响应将是-1,在收到这样的响应后,您的程序必须立即退出以接收错误答案判决。否则,你可以得到其他判决。

Example

input

Copy

3

1

0

1

1

0

2

1

0

output

Copy

- 1

! 1

- 1

- 1

! 2

- 2

- 1

! 3

 

请注意例如,数字6的单位位数是2,因为6的二进制表示法是110。对于13,单位比特数是3,因为1310 = 11012.在第一个测试用例中,n = 1,因此输入是数字1。n减1后,它变成0,所以它的单位比特数是0.l在第三个测试案例中,n=3,在二进制表示中看起来像310 112,所以输入是1的个数,也就是2。减去2后,n = 1,所以单位比特数现在是1。n减1后,它等于0。请注意,输入和输出示例中的空行是为了清晰起见而显示的,在实际交互中没有出现。

注意:交互式问题输入输出只能用c++的输入输出!!!

题解:
我们从二进制0位开始询问某位是否有1即可,由于状态会不断改变,记录一下上次变换的值,下次减掉,就能做到只有单个位置发生变化,

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
using namespace std;
//#define int long long
const int N = 2e6 + 10;
typedef pair<int, int> PII;
typedef long long ll;
void solve() 
{
	int n;
	cin >> n;
	int t = 0;
	int ans = 0;
	int cnt = 0;
	for(int i = 0;i <= 30;i++)
	{
		int x = (1 << i);
		cout <<"- "<<x - t <<"\n";
//		printf("- %d\n",x - t);
		int a;
		cin >> a;
//		scanf("%d",&a);
		if(a == n - 1)
		{
			ans += x;
			cnt ++;
		}
		if(cnt == n)
		{
			cout <<"! "<<ans<<"\n";
//			printf("! %d\n",ans);
			return ;
		}
		t = x;
	}
}

//1 2 4
signed main() 
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
//scanf("%d",&t);
	while (t--) 
	{
		solve();
	}
}
//1 1 1 0 1

//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//0 1 1 1 1
//0 1 1 1 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值