CF1665D GCD Guess
常规做法是 CRT,这里写一写更简单的做法。
\(\gcd(x+a,x+b)=\gcd(x+a,\mid b-a \mid)\)
数据范围和猜测次数启示我们在二进制下一位一位的确定 \(x\)。
为了消除高位对低位的影响,从低位到高位猜。
假设猜到了从右到左第 \(i\) 位,那么记前面的 \(i-1\) 位组成的数值为 \(x\)。
那么构造出 \(a=2^{i-1}-x\),\(b=2^{i-1}+2^{i}-x\)。
因为如果 \(i\) 位上是 \(0\),那么 \(x+a\) 从右到左有 \(i-1\) 个 \(0\),所以当 \(\gcd(x+a,x+b)=2^{i-1}\) 时,\(i\) 位为 \(0\),否则为 \(1\)。
#include <bits/stdc++.h>
typedef long long ll;
void solve() {
int ans = 0;
for(int i = 0; i < 30; ++i) {
std::cout << "? " << (1 << i) - ans << " " << (1 << i) - ans + (1 << (i + 1)) << "\n";
fflush(stdout);
int x;
std::cin >> x;
if(x == (1 << (i + 1))) ans |= 1 << i;
}
std::cout << "! " << ans << "\n";
fflush(stdout);
}
int main() {
// std::ios::sync_with_stdio(false);
// std::cin.tie(nullptr);
int _;
std::cin >> _;
while(_--) solve();
return 0;
}