CF768C题解

· · 题解

Description

## Solution 首先给出这道题中用到的十分重要的几个性质: 1. `i & (n - i - 1) = 0` 这个性质十分好证,将 $i$ 以及 $n - i - 1$ 的二进制写出来你就会发现他们的 $0$ 和 $1$ 是“插空站”的,或者反过来想,当你有这样的两个 $n$ 位二进制数,你将他们相加时每一位都会进位,最后得到的结果自然是 $2^n$,而且我们发现,$i$ 和 $n - i - 1$ 是关于 $\frac{n}{2}$ 对称的。 2. `(n - 1) & k = k` 这个性质也十分好证,易得 $n - 1$ 的二进制表示为连续的 $\log_{2}{n}$ 个 $1$, 它和任何数做位运算与自然是这个数本身了。 3. `0 & p = p` 证明略。 那如何将这个性质运用在这道题当中呢? 首先,当 $k < n - 1$,我们将 $k$ 与 $n - 1$ 配成一对,由性质 $2$ 得这一对数字对答案的贡献恰好为 $k$,再将 $n - k - 1$ 和 $0$ 配成一对,由性质 $3$ 得这一对数字对答案的贡献为 $0$。接下来,我们只需要使剩下的数对对答案的贡献均为 $0$ 就可以了,这不是有性质 $1$ 吗?枚举剩下的数字并输出相应的数对就可以了。 接下来是当 $k = n - 1$ 的情况。~~由样例得~~我们自己手推了一下发现,当 $n = 2$ 和 $n = 4$ 找不出合法的分法,接下来思考 $n > 4$ 的情况。我们可以把 $0$ 至 $n - 1$ 的二进制表示列出来,如下表: [![HZYqs0.png](https://s4.ax1x.com/2022/02/04/HZYqs0.png)](https://imgtu.com/i/HZYqs0) 由性质 $2$ 结合表格可得,`(n - 1) & (n - 2) = n - 2` ,这时候还剩下一个最低位的 $0$ 要补上,正好,$n - 3$ 的最低位是 $1$,$1$ 只有最低位是 $1$, 于是易得 `(n - 3) & 1 = 1` ,这下把 $k$ 凑齐了,而根据性质 $1$ 中的“对称性”可得,我们需要把 $0$ 和 $2$ 凑成一对,剩下的数只需要由性质 $1$ 输出对应数对就好了。 ## Code ```cpp #include<iostream> using namespace std; int t, n, k; int main() { cin >> t; while(t --) { cin >> n >> k; if(k == n - 1) { if(k <= 4) { cout << "-1\n"; continue; } cout << 1 << ' ' << n - 3 << '\n'; cout << n - 1 << ' ' << n - 2 << '\n'; cout << "0 2\n"; for(int i = 3; i < (n >> 1); ++ i) cout << i << ' ' << n - i - 1 << '\n'; continue; } cout << k << ' ' << n - 1 << '\n'; if(k != 0) cout << "0 " << n - k - 1 << '\n'; for(int i = 1; i < (n >> 1); ++ i) { if(i == k || i == n - k - 1) continue; cout << i << ' ' << n - i - 1 << '\n'; } } return 0; } ```