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;
}
posted @ 2023-02-04 11:27  yoshinow2001  阅读(21)  评论(0编辑  收藏  举报