2021.04.17 日常总结——第一道自己想出来的交互题

CF1407C   Chocolate   Bunny \color{green}{\texttt{CF1407C Chocolate Bunny}} CF1407C Chocolate Bunny

[Problem] \color{blue}{\texttt{[Problem]}} [Problem]

你需要猜测一个长度为 n n n 的排列。你最多有 2 × n 2 \times n 2×n 次机会,每次机会可以询问 a i m o d    a j a_{i} \mod a_{j} aimodaj。输出这个排列。

[Solution] \color{blue}{\texttt{[Solution]}} [Solution]

可以询问两个数 ( i , j ) (i,j) (i,j),我们先询问 a i m o d    a j a_{i} \mod a_{j} aimodaj,记为 x x x,再询问 a j m o d    a i a_{j} \mod a_{i} ajmodai,记为 y y y

  • a i < a j a_i < a_j ai<aj 时,我们可以知道 a i = x a_{i}=x ai=x,但是 y < a i y<a_{i} y<ai,即 y < x y<x y<x
  • a i > a j a_{i}>a_{j} ai>aj 时,同理, a j = y , x < a j a_{j}=y,x<a_{j} aj=y,x<aj,即 x < y x<y x<y

所以我们可以通过判断 x , y x,y x,y 的大小来判断 a i a_{i} ai 或者 a j a_{j} aj 的值,即:

  • x < y x<y x<y 时, a j = y a_{j}=y aj=y
  • x > y x>y x>y 时, a i = x a_{i}=x ai=x

每次询问我们可以知道 a i , a j a_{i},a_{j} ai,aj 中的较小的一个数字

所以我们从前往后扫一遍,记区间 [ 1 , i − 1 ] [1,i-1] [1,i1] 中尚未知道的数字(即最大的那个数字)是 a sub a_{\texttt{sub}} asub,询问 ( sub , i ) (\texttt{sub},i) (sub,i) 间的关系。这样,我们只需要 2 ( n − 1 ) 2(n-1) 2(n1) 次询问即可得到原排列。

最后注意三点:

  1. 最后,原排列中最大的数字我们是不知道的,要特判。
  2. 这个算法当 n = 1 n=1 n=1 时会失效,所以特判 n = 1 n=1 n=1
  3. 输入输出的格式。

[code] \color{blue}{\texttt{[code]}} [code]

int n,sub,a[10100];
int main(){
	scanf("%d",&n);sub=1;
	if (n==1){printf("! 1");return 0;}
	for(int i=2,x,y;i<=n;i++){
		printf("? %d %d\n? %d %d\n",sub,i,i,sub);
		fflush(stdout);//清空输出文件 
		scanf("%d%d",&x,&y);
		if (x<y) a[i]=y;
		else a[sub]=x,sub=i;
		if (i==n) a[sub]=n;
	}
	printf("!");
	for(int i=1;i<=n;i++)
		printf(" %d",a[i]);
	fflush(stdout);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值