Codeforces Round #838 (Div. 2)-D. GCD Queries-GCD、交互
题目:https://codeforces.com/problemset/problem/1762/D
有一个0~n-1的排列,你要在至多2n次询问中找到两个位置x,y,使得\(p_x,p_y\)至少有一者为0.每次询问可以问两个不同的i,j,测评机会回答\(\gcd(p_i,p_j)\)的值。
题解:
\(\gcd(0,x)=x\)
以及这题一个很关键的地方是,我不需要确定具体哪个是0,只需要保证两个中有一个是0就可以了。
这样子我们考虑如何“排除某个地方一定不是0”,假设有三个位置\(i,j,k\):
- 若\(\gcd(p_i,p_k)=\gcd(p_j,p_k)\),则\(p_k\)一定非零,否则\(p_i=p_j\)和全排列矛盾。
- 若\(\gcd(p_i,p_k)>\gcd(p_j,p_k)\),则\(p_j\)一定非零,否则\(\gcd(p_j,p_k)=p_k\geq \gcd(p_i,p_k)\)。
- 若\(\gcd(p_i,p_k)<\gcd(p_j,p_k)\),同理
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
int query(int x,int y){
cout<<"? "<<x<<' '<<y<<endl;
fflush(stdout);
int r;cin>>r;return r;
}
int main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
int x=1,y=2;
rep(i,3,n){
int r1=query(i,x);
int r2=query(i,y);
if(r1>r2)y=i;
else if(r1<r2)x=i;
}
cout<<"! "<<x<<' '<<y<<endl;
fflush(stdout);
int ret;cin>>ret;
}
return 0;
}