翻译:
这是一个互动的问题。
我们向您隐藏了一个长度为𝑛的排列𝑝,由从1到𝑛的元素组成。你想猜一下。为此,你可以给我们2个不同的索引𝑖和𝑗,我们将回复𝑝𝑖mod𝑝𝑗(𝑝𝑖除以𝑝𝑗的余数)。
我们有足够的耐心回答最多2⋅𝑛的问题,所以你应该符合这个限制。你能做到吗?
提醒一下,长度为𝑛的排列是一个由𝑛个从1到𝑛的不同整数以任意顺序组成的数组。例如,[2,3,1,5,4]是一个排列,但[1,2,2]不是一个排列(2在数组中出现两次),[1,3,4]也不是一个排列(𝑛=3,但数组中有4)。
输入
输入的唯一一行包含一个整数𝑛(1≤𝑛≤104)-排列的长度。
交互
互动从阅读𝑛开始。
那么你最多可以进行2⋅𝑛的查询,方法如下:
”?X y”(1≤𝑥,𝑦≤𝑛,𝑥≠𝑦)。
在每一个之后,您应该读取一个整数𝑘,它等于𝑝𝑥mod𝑝𝑦。
当你猜出排列后,打印一行“!”(不带引号),后面跟着数组𝑝和quit。
打印查询后,不要忘记输出行尾并刷新输出。否则,您将得到闲置限制超过。要做到这一点,请使用:
c++中的fflush(stdout)或count .flush();
Java中的System.out.flush();
Pascal中的flush(输出);
Python中的stdout.flush();
有关其他语言,请参阅文档。
收到“-1”后立即退出,你将看到错误答案判决。否则,您可能会得到一个任意的裁决,因为您的解决方案将继续从一个封闭的流中读取。
修改格式
在第一行输出𝑛(1≤𝑛≤104)。在第二行中,打印𝑛整数的排列𝑝1,𝑝2,…,𝑝𝑛。
例子
inputCopy
3.
1
2
1
0
outputCopy
? 1 2
? 3 - 2
? 1 3
? 2 1
! 1 3 2
思路:2*n次查询,刚开始没有思路,然后写了下,发现,如果a>b,那么a%b一定是小于b的,如果b>a,a%b一定是a,那么a一定比可以取余的大,因为取余过后肯定是比a,b小的。所以我们每次对相同的两个位置,轮流查询,答案大的那个就是其中小的那个,因为小的被比其大的数取余肯定是本身,所以我们可以两次得到一个答案,之后如果剩下一个了,就可以break了,打个标记就可以确定最后一个在哪里了。
代码:
/*Looking! The blitz loop this planet to search way
Only my RAILGUN can shoot it 今すぐ
身体中を 光の速さで
駆け巡った確かな予感
掴め! 望むものなら残さず
輝ける自分らしさで
信じてるよ あの日の誓いを
この瞳に光る涙それさえも 強さになるから
*/
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long ll;
inline __int128 read(){
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
int n;
int an[10005];
int ff,ns;
int a,b;
int main(){
ios::sync_with_stdio(false);
cin>>n;
if (n==1) {
printf("! 1\n");return 0;
}
memset(an, -1, sizeof an);
queue<int>q;
for (int i=1; i<=n; i++) {
q.push(i);
}
while (1) {
if (q.size()==1) {
break;
}
ff=q.front();
q.pop();
ns=q.front();
q.pop();
cout<<"? "<<ff<<" "<<ns<<endl;
cin>>a;
cout<<"? "<<ns<<" "<<ff<<endl;
cin>>b;
if (a>b) {
an[ff]=a;
q.push(ns);
}
else{
an[ns]=b;
q.push(ff);
}
}cout<<"! ";
for (int i =1; i<=n; i++) {
if (an[i]==-1) {
cout<<n<<" ";
// printf("%d ",q.front());
}
else{
cout<<an[i]<<" ";
// printf("%d ",an[i]);
}
}
return 0;
}