D. GCD Guess(gcd性质与二进制位)

文章描述了一个在Codeforces平台上的编程竞赛问题,涉及到一个交互式的谜题,要求在不超过30次查询内找出隐藏的正整数z。解题策略是通过二进制位的判断,利用最大公约数与数字二进制表示的关系来逐步缩小答案范围。
摘要由CSDN通过智能技术生成

Problem - D - Codeforces

这是一个互动的问题。有一个正整数1 <x <109,你必须猜。在一个查询中,您可以选择两个正整数a和b。作为这个查询的答案,您将得到gcd(z + a, x + b),其中gcd(n, m)是数字n和m的最大公约数。要猜出一个隐藏的数字z,你只能进行不超过30次的查询。输入输入的第一行包含一个整数t (1 < t < 1000),表示测试用例的数量。你必须猜测的整数z满足约束:(1 < < 10°)。交互隐藏的数字z在交互开始之前是固定的,不依赖于您的查询。要猜出每个z,你可以用下面的方法进行不超过30次的查询。."?A B“(1 < a,b< 2.10°,a +b)。对于这个查询,您将得到gcd(æ + a, æ + b)。当你知道的时候,用下面的格式打印一行。”。!x”(1 < x < 109)。之后继续解决下一个测试用例。如果一个查询超过30个,或者查询无效,交互器将立即终止,程序将收到错误答案的判决。打印完每个查询后,不要忘记输出行尾并刷新输出缓冲区。否则,您将得到超过怠速限制的判决。要进行冲洗使用:Fflush (stdout)或cout。c++中的flush ();Java中的System.out.flush();Pascal中的flush(输出);Python中的stdout.flush();阅读其他语言的文档。

Example

input

Copy

2

1

8


1

output

Copy

? 1 2

? 12 4

! 4
? 2000000000 1999999999

! 1000000000

题解:
由于这是个交互式问题,并且需要在30次内求出答案

并且x <= 1e9,遇到这种形式,要么是二分,要么从二进制位上着手

本题二分没有什么思路,那么从二进制位上考虑

首先我们应该知道一个问题

假如一个数x的二进制结尾为(..000),那么gcd(x,2^3) = 2^3

假如一个数x的二进制结尾为(..00),那么gcd(x,2^3)肯定不为2^3

我们依照这样的思路来判断二进制每位是否有1

假设r为低位剩余部分

x - r即为当前要判断的位数

如何判断第n位是否有1,

假设第n位有1,此位加1,那么1 ~ n位为0,那么他与2^n的最大公因数应该是2^n,否则不是

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define int long long
const int N = 4e5 + 10;
typedef pair<int, int> PII;
int n,k;
int b[N];
int a[N];
int add,cnt,ans;
void query(int a,int b)
{
	cout <<"? "<<a<<" "<<b<<"\n";
}
void solve() 
{
	int r = 0;
	for(int i = 1;i <= 30;i++)
	{
		query((1 << (i- 1)) - r,(1 << i )+ (1 << (i-1)) - r);
		int t;
		cin >> t;
		if(t == (1 << i))
		{
			r |= 1 << (i - 1);
		}
	}
	cout <<"!" <<" "<<r<<"\n"; 
}

//1 2 4
signed main() 
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
//scanf("%lld",&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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值