C. And Matching
https://codeforces.com/contest/1631/problem/C
①我们首先可以想到
k
=
0
k=0
k=0 的情况,那就是对称的构造,也就是
(
i
,
n
−
i
−
1
)
(i, n - i - 1)
(i,n−i−1) 这么去构造。
②那么若 k ≠ 0 k \neq 0 k=0 时,我们就想,是否我们可以首先使得一个“对子”直接值为 k k k ,其余的都为 0 0 0 呢。那么如果要让一对值直接为 k k k ,那就让 k k k 直接去 & \& & 上一个全 1 1 1 的数就好了,也就是 n − 1 n-1 n−1 ,然后我们发现这样的话 k k k 是不可以为 n − 1 n-1 n−1 的,那么我们就先讨论 k ≠ n − 1 k \neq n-1 k=n−1 的情况。让 k k k 与 n − 1 n-1 n−1 成一对之后,我们希望其它对都是 0 0 0 ,那么我思考这样操作( k k k 与 n − 1 n-1 n−1 配对)在①的构造方式上发生了哪些破坏呢,实际上就是只破坏了 ( 0 , n − 1 ) , ( k , n − 1 − k ) (0,n-1),(k,n-1-k) (0,n−1),(k,n−1−k) 这个两个对,那么我们显然可以发现,让 k k k 和 n − 1 n-1 n−1 配对后,让 0 0 0 和 n − 1 − k n-1-k n−1−k 配对就完事了,其它的都保持原构造,这样全局的值就为 k k k 了。
③那么我们现在就考虑当 k = n − 1 k=n-1 k=n−1 时的构造方式,那么我们往简单了想,能否构造个 n − 2 n-2 n−2 和 1 1 1 出来,我们发现是可以的,我们可以形成 ( n − 1 , n − 2 ) (n-1,n-2) (n−1,n−2) 以构造出 n − 2 n-2 n−2 ,再由 ( 1 , n − 3 ) (1,n-3) (1,n−3) 造出 1 1 1 ,被破坏的 0 0 0 和 2 2 2 组合成 ( 0 , 2 ) (0,2) (0,2) 形成 0 0 0 ,其余的构造如①一样,这样总和就为 n + 2 + 1 = n − 1 n+2 +1=n-1 n+2+1=n−1 了,实际上就是在①的基础上,调整 ( 0 , n − 1 ) ( 1 , n − 2 ) ( 2 , n − 3 ) (0,n-1)(1,n-2)(2,n-3) (0,n−1)(1,n−2)(2,n−3) 的顺序。当然,我们会发现这样的情况只使用于 n ≥ 4 n \geq 4 n≥4 ,而且我们发现当 n = 4 n = 4 n=4 时是无解的。至此我们就考虑完了所有情况。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, k, pa[N], pb[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &k);
for (int i = 0; i <= (n - 1) / 2; ++i) {
pa[i] = i; pb[i] = n - i - 1;
}
if (n == 4 && k == 3) {
puts("-1");
}
else if (k == 0) {
for (int i = 0; i <= (n - 1) / 2; ++i) {
printf("%d %d\n", i, n - i - 1);
}
}
else if (k < n - 1) {
printf("0 %d\n", n - 1 - k);
printf("%d %d\n", k, n - 1);
for (int i = 0; i <= (n - 1) / 2; ++i) {
if (i != 0 && i != k && i != n - 1 - k) {
printf("%d %d\n", i, n - 1 - i);
}
}
}
else {
printf("%d %d\n", n - 1, n - 2);
printf("2 0\n");
printf("1 %d\n", n - 3);
for (int i = 0; i <= (n - 1) / 2; ++i) {
if (i != 0 && i != 1 && i != 2 && i != k && i != n - 1 - k) {
printf("%d %d\n", i , n - i - 1);
}
}
}
}
}