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;
}
posted @ 2024-01-25 00:16  jvdyvan  阅读(11)  评论(0)    收藏  举报