C. Chocolate Bunny
题目链接
题目描述
给一个长度为
n
n
n的排列
p
n
p_n
pn,由从
1
1
1到
n
n
n的整数组成。要求通过询问猜出排列的顺寻,有最多
2
n
2n
2n次询问机会。
询问方式如下:
"
?
x
y
"
(
1
≤
x
,
y
≤
n
,
x
≠
y
)
"?\quad x \quad y"(1\leq x,y\leq n,x\neq y)
"?xy"(1≤x,y≤n,x=y)系统将会返回
p
x
m
o
d
p
y
p_xmod\ p_y
pxmod py的值。
题目分析
细节问题暂不讨论,主要讨论如何询问:
对于两个不相等的正整数
x
x
x和
y
y
y,假如
x
>
y
x\gt y
x>y,
x
m
o
d
y
x\ mod\ y
x mod y得到的一定是小于
y
y
y的数,而
y
m
o
d
x
y\ mod\ x
y mod x得到的则是
y
y
y本身。
如果令
a
=
x
m
o
d
y
a = x \ mod \ y
a=x mod y,
b
=
y
m
o
d
x
b = y \ mod \ x
b=y mod x,那么
x
>
y
x\gt y
x>y时,
{
a
<
y
b
=
y
⇒
a
<
b
\begin{cases}a\lt y\\b=y\end{cases}\Rightarrow a\lt b
{a<yb=y⇒a<b。
通过
a
<
b
a \lt b
a<b也可推出
a
<
y
,
b
=
y
,
x
>
y
a \lt y,b=y,x>y
a<y,b=y,x>y。
x
<
y
x\lt y
x<y时同理。
因此可以通过比较两个数互相取模的结果来猜出其中一个数。
代码
#include <iostream>
#include <cstdio>
using namespace std;
int ans[10001];
int query(int x, int y) {
printf("? %d %d\n", x, y);
fflush(stdout);
int respond;
scanf("%d", &respond);
return respond;
}
int main() {
int n;
cin >> n;
int p = 1, a, b;
for (int i = 2; i <= n; i++) {
a = query(p, i);
b = query(i, p);
if (a > b) {
ans[p] = a;
p = i;
} else { // a < b
ans[i] = b;
}
}
// 前面只填上了 1 到 n - 1,还剩 n 未填,而 p 最后即代表最大数 n 的位置
ans[p] = n;
printf("!");
for (int i = 1; i <= n; i++)
printf(" %d", ans[i]);
system("pause");
}