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;
}
posted @ 2022-05-02 20:50  Nylch  阅读(42)  评论(0编辑  收藏  举报