科学委员会向你隐藏了一个包含从 $1$ 到 $N$ 的所有整数的排列 $P$ ($3 \le N \le 256$)。你需要找到它。排列 $P$ 是固定的(评测系统不是自适应的)。
在你的尝试过程中,你可以进行询问,询问的参数是另一个包含从 $1$ 到 $N$ 的所有整数的排列 $V$:
query(V) 将返回 $\sum_{i=1}^{N-1} |P[V[i]] - P[V[i+1]]|$。
通过进行若干次询问,你需要发现排列 $P$,或者任何与 $P$ 不可区分的排列 $P'$。如果两个排列在所有可能的询问方式下都产生相同的结果,则称它们是不可区分的。
交互
这是一个交互式问题。你必须提交一个包含以下约束的源文件:
C / C++: #include "permutationc.h" |
你必须包含此头文件,以便正确编译你的代码并将其与科学委员会的代码链接。 |
C / C++: void solve(int N); |
你的解决方案必须写在这个函数内。你可以自由编写和调用其他函数,但不允许编写 main() 函数。 |
C / C++: int query(int V[]); 或仅 C++: int query(std::vector<int> V); |
每当你想要进行询问时,调用此函数,并传入一个包含从 $1$ 到 $N$ 的所有整数的排列 $V$ 作为参数。你的得分将取决于你调用此函数的次数。 |
C / C++: void answer(int P[]); 或仅 C++: void answer(std::vector<int> P); |
当你确信已经发现了排列 $P$ 时,调用此函数并传入 $P$ 作为参数。调用此函数将终止程序。 |
注意,当作为参数提供时,排列 $P$ 和 $V$ 均表示为从 $0$ 开始索引的 int 数组或 std::vector<int>。
样例
输入格式 1
(无)
输出格式 1
// C 语言示例
#include "permutationc.h"
void solve(int N) {
if (N == 2) {
int V[] = {1, 2};
int qAns = query(V);
if (qAns == 1) {
int P[] = {1, 2};
answer(P);
}
}
}输入格式 2
(无)
输出格式 2
// C++ 语言示例
#include "permutation.h"
void solve(int N) {
if (N == 2) {
std::vector<int> V = {1, 2};
int qAns = query(V);
if (qAns == 1) {
std::vector<int> P = {1, 2};
answer(P);
}
}
}样例评测程序
对于本地测试,你可以从 CMS 下载两个文件:sample_grader.cpp 和 permutation.h。
评测程序从标准输入读取一个整数 $N$(隐藏排列的大小)和 $N$ 个不同的整数(隐藏的排列)。然后,评测程序调用你必须实现的 solve() 函数。
在标准输出上,评测程序将输出:
(a) 对于每一次 query() 调用:被询问的排列和询问的答案;
(b) 对于 answer() 调用:判定结果(Correct 或 Wrong Answer)、$N$ 和 $Q$(排列的大小以及你使用的询问次数)。
子任务
(1) $3 \le N \le 7$ (15 分) (2) $3 \le N \le 50$ (35 分) (3) $3 \le N \le 256$ (50 分)
评分
每个测试用例的评分如下: 如果你未能发现其中一个正确的排列,则得分为 0%。 否则,令 $Q$ 为你解决该测试用例所需的询问次数。
(a) 如果 $Q \le N$,则获得 100% 的分数。 (b) 如果 $N \le Q \le 2 \times N$,则获得 $(100 - 40 \times (Q - N) / N)\%$ 的分数(在 60% 到 100% 之间,随着 $Q$ 的减小而增加)。 (c) 如果 $2 \times N \le Q \le N^2$,则获得 $(60 - 40 \times (Q - 2 \times N) / (N^2 - 2 \times N))\%$ 的分数(在 20% 到 60% 之间,随着 $Q$ 的减小而增加)。 (d) 如果 $N^2 \le Q$,则获得 20% 的分数。
该任务的总分将四舍五入到小数点后 2 位。
科学委员会拥有一个得分超过 98 分的解决方案。