CF1630A. And Matching
题目大意
\(给你两个数字n和k,n是2的幂,问你能不能用0到n-1的n个数字组成\frac{n}{2}对(p_i, q_i)使得\sum\limits_{i=1}^{\frac{n}{2}}(p_i, q_i) = k\)
思路
\(定义一个函数c使得c(x)的在二进制表示上每一位都和x不同,例如c(1001110_2) = 0110001_2;\)
$我们可以发现c(x) = x $ ^\((n - 1)。\)
\(这样我们可以把问题分成3种情况来处理:\)
\(当k = 0时,我们可以构造\frac{n}{2}对(i, c(i))即可。\)
\(当0 < k < n - 1时,我们可以构造(0, c(k))、(k, n - 1) 然后剩下的就(i, c(i))。\)
\(当k = n - 1时,很明显当n=4时无法构造,其他时候可以按下面的方法来\):
\(构造(n - 1, n - 2);\) -> \((n - 1)\) & \((n - 2) = n - 2\)
\(构造(n - 3, 1);\) ->\((n - 3)\) & \(1 = 1\)
\(构造(0, 2);\)
\(剩下的就(i, c(i))。\)
ac代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 inf = 1e18;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
void solve() {
int n, target;
cin >> n >> target;
auto c = [&](int x) {
return x ^ (n - 1);
};
if (target == 0) {
for (int i = 0; i < n/2; i++)
cout << i << ' ' << c(i) << endl;
} else if (target < n - 1) {
cout << target << ' ' << n - 1 << endl;
cout << 0 << ' ' << c(target) << endl;
for (int i = 1; i < n/2; i++)
if (i != target && i != c(target))
cout << i << ' ' << c(i) << endl;
} else {
if (n == 4) cout << "-1\n";
else {
cout << n - 1 << ' ' << n - 2 << endl;
cout << n - 3 << ' ' << 1 << endl;
cout << 0 << ' ' << 2 << endl;
for (int i = 3; i < n/2; i++)
cout << i << ' ' << c(i) << endl;
}
}
}
int main() {
ios::sync_with_stdio(0); cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t --) solve();
return 0;
}