CF round#669 div2 C题

6 篇文章 0 订阅
4 篇文章 0 订阅

C. Chocolate Bunny

题目链接

  • time limit per test: 1 second

  • memory limit per test: 256 megabytes

  • input: standard input

  • output: standard output

This is an interactive problem.

We hid from you a permutation p p p of length n n n, consisting of the elements from 1 1 1 to n n n. You want to guess it. To do that, you can give us 2 different indices i i i and j j j, and we will reply with p i   m o d   p j p_i \ mod \ p_j pi mod pj(remainder of division p i p_i pi by p j p_j pj).

We have enough patience to answer at most 2 ⋅ n 2⋅n 2n queries, so you should fit in this constraint. Can you do it?

As a reminder, a permutation of length n n n is an array consisting of n n n distinct integers from 1 1 1 to n n n in arbitrary order. For example, [ 2 , 3 , 1 , 5 , 4 ] [2,3,1,5,4] [2,3,1,5,4] is a permutation, but [ 1 , 2 , 2 ] [1,2,2] [1,2,2] is not a permutation ( 2 2 2 appears twice in the array) and [ 1 , 3 , 4 ] [1,3,4] [1,3,4] is also not a permutation ( n = 3 n=3 n=3 but there is 4 4 4 in the array).

Input

The only line of the input contains a single integer n ( 1 ≤ n ≤ 1 0 4 ) n(1\leq n \leq 10^4) n(1n104) — length of the permutation.

Interaction

The interaction starts with reading n n n.

Then you are allowed to make at most 2 ⋅ n 2⋅n 2n queries in the following way:

  • “? x y” ( 1 ≤ x , y ≤ n , x ≠ y ) (1≤x,y≤n,x≠y) (1x,yn,x=y).

After each one, you should read an integer k k k, that equals p x   m o d   p y p_x\ mod\ p_y px mod py.

When you have guessed the permutation, print a single line "! " (without quotes), followed by array p p p and quit.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

  • fflush(stdout) or cout.flush() in C++;
  • System.out.flush() in Java;
  • flush(output) in Pascal;
  • stdout.flush() in Python;
  • see documentation for other languages.

Exit immediately after receiving “-1” and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

Hack format

In the first line output n ( 1 ≤ n ≤ 1 0 4 ) n(1\leq n \leq 10^4) n(1n104). In the second line print the permutation of n n n integers p 1 , p 2 , . . . , p n p_1, p_2, ..., p_n p1,p2,...,pn.

Example
input
3
1
2
1
0
output
? 1 2
? 3 2
? 1 3
? 2 1
! 1 3 2

题目大意

给定整数n,让你猜出一个1到n的排列

猜的过程可以进行至多2*n次提问,提问的格式为? x y,将会返回第x个元素对第y个元素取模的结果

最后以! 开头,输出这个排列

解法

其实 2 ∗ n 2*n 2n次提问推导 n n n个元素,容易想到(容易吗?),使用2次提问就可以推导出1个元素。

怎么推导呢?

假设这两个数是 x x x y y y,且 x < y x<y x<y

那么两次提问将会得到两个结果:

  • m o d 1 = x   m o d   y mod1 = x \ mod \ y mod1=x mod y
  • m o d 2 = y   m o d   x mod2 = y \ mod \ x mod2=y mod x

由于假设 x < y x<y x<y,显然有 m o d 1 = x mod1=x mod1=x,而 m o d 2 mod2 mod2是对 x x x取模,由模运算的特点可知 m o d 2 < x mod2<x mod2<x恒成立,也就有

  • m o d 2 < x = m o d 1 mod2<x=mod1 mod2<x=mod1

也就有了这样的结论:

  • 如果 m o d 2 < m o d 1 mod2<mod1 mod2<mod1,那么 m o d 1 = x mod1=x mod1=x

  • 类似的有:如果 m o d 1 < m o d 2 mod1<mod2 mod1<mod2,那么 m o d 2 = y mod2=y mod2=y

因此只要每次取出两个未知元素,让他们互相对对方取模,就能得到一个元素的值,进行2*n次这样的询问就能得到n个元素的值

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
int a[maxn]; 
int q[maxn<<1], head, tail;
int main() {
	int n; cin>>n;
	head = tail = 0;
	for(int i = 0; i < n; ++i)
		q[tail++] = i;
	int last = n * (n+1) / 2;

	while(head < tail-1) {
		int x = q[head++];
		int y = q[head++];
		cout<<"? "<<x+1<<" "<<y+1<<endl;
		cout<<"? "<<y+1<<" "<<x+1<<endl;
		int mod1, mod2; cin>>mod1>>mod2;
		if(mod1 < mod2) {
			q[tail++] = x;
			a[y] = mod2;
			last -= mod2;
		}
		else {
			q[tail++] = y;
			a[x] = mod1;
			last -= mod1;
		}
	}
	a[q[head]] = last;
	
	cout<<"!";
	for(int i = 0; i < n; ++i)
		cout<<" "<<a[i];
	cout<<endl;
	cout.flush();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值