这是一个互动的问题。有一个正整数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