本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2022-04-14 21:17:26
题解思路:
有一个很显然的性质:
$x\ n - x$ 的二进制每一位都是相反的。
所以我们可一构造出 $k=0$ 时的情况。
当$k \ne n-1$ 的时候:
我们就可以让 $k$ 和 $n - 1$ 组成一组。
再让 $n - k + 1$ 和 $0$ 构成一组
接下来就是 $k = n-1$ 的情况:
若 $k=n-1$,那我们就不能 $n - 1$ 和 $n - 1$,$0$ 和 $0$ 分成一组。
因为要 $n\ge 4$,即二进制至少有两位。
$(0){10} = (0){2}$, $(1){10} = (1){2}$, $(2){10} = (10){2}$, $(3){10} = (11){2}$。
$(n - 4){10} = ((??????...-1)11){2}$、
$(n - 3){10} = (?????...00){2}$、
$(n - 2){10} = (?????...01){2}$、
$(n - 1){10} = (?????...10){2}$、
$(n){10} = (??????... 11){2}$。
那么我们可以 $n - 2$ 和 $3$。
$n - 4$ 和 $1$。
$n - 1$ 和 $n - 3$。
$2$ 和 $0$。
特殊情况 $n = 4 , k = 3$ 时构造不出来,输出 $-1$,其他情况都有解,把这种情况特判掉就可以了。
AC CODE:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1 << 20;
int a[N];
int main() {
int T;
scanf ("%d" , &T);
while (T --) {
int n , k;
scanf ("%d%d" , &n , &k);
if (n == 4 && k == 2)puts("-1");\/\/无解情况
else if (k == 0) {\/\/k=0时
for (int i = 0; i < n \/ 2; ++ i)
printf ("%d %d\n" , i , n - 1 - i);
}else if (k != n -1) {\/\/k!=n-1时
printf ("%d %d\n" , n - 1 , k);
printf ("%d %d\n" , n - 1 - k , 0);
for (int i = 1; i < n \/ 2; ++ i)
if (i != k && i != n - 1 - k)
printf ("%d %d\n" , i , n - 1 - i);
}else {\/\/k=n-1的情况
printf ("%d %d\n" , n - 2 , 3);
printf ("%d %d\n" , n - 4 , 1);
printf ("%d %d\n" , n - 1 , n - 3);
printf ("%d %d\n" , 2 , 0);
for (int i = 4; i < n \/ 2; ++ i)
printf ("%d %d\n" , i , n - i - 1);
}
}
return 0;
}

鲁ICP备2025150228号