牛客竞赛 1021 1022 点名

题意

n个同学 , 学号为1-n
今天来了n-1/n-2个同学 , 问哪些同学没来

思路

对于n-1个同学 , 异或即可

对于n-2个同学 , 异或后结果中 , 为1的地方特殊 , 意味着两个人的学号在此处不同

那么可以将1-n分为两类 , 从而再次使用第一种方法求解

如何找到某个为1的地方呢 ? 可以借鉴树状数组的lowbit()

那么如果是用字符串呢 ?
考虑把A-Z , a-z, 0-9作为62进制 , 这样6位可以表示出所有情况

由于最长20 , 那么就是120位的bitset可以存储下一个学号

这样就一样了

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long int

// 快速读入
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}

const int N = 1e4 + 10;

bitset<120> a[N << 1];
bitset<120> encode(const string &t) {
    bitset<120> result;
    for (int i = 0 ; i< 120; i++) result[i] = true;

    int bitpos = 0;
    for (char c : t) {
        int val = 0;
        if ('0' <= c && c <= '9') {
            val = c - '0';        // 0-9
        } else if ('A' <= c && c <= 'Z') {
            val = c - 'A' + 10;   // 10-35
        } else if ('a' <= c && c <= 'z') {
            val = c - 'a' + 36;   // 36-61
        } else {
            val = 0b111111;              // 其他字符编码为0
        }
        for (int i = 0; i < 6; ++i) {
            result[bitpos + i] = (val >> i) & 1;
        }
        bitpos += 6;
    }
    return result;
}

// 解码bitset<120>为字符串,长度固定20个字符
string decode(const bitset<120> &b) {
    string res = "";
    for (int i = 0; i < 20; i++) {
        int num = 0;

        for (int j = 5; j >= 0; j--) {
            num = (num << 1) | b[i * 6 + j];
        }
        if (num >= 0 && num <= 9)
            res.push_back(num + '0');
        else if (num >= 10 && num <= 35)
            res.push_back('A' + (num - 10));
        else if (num >= 36 && num <= 61)
            res.push_back('a' + (num - 36));

    }
    return res;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin>>n;
    bitset<120> ans(0);
    bitset<120> ans1(0);
    bitset<120> ans2(0);

    // 输入 2*n - 2 个字符串,编码后异或
    for (int i = 1; i <= n * 2 - 2; i++) {
        string t;
        cin >> t;
        a[i] = encode(t);
        ans ^= a[i];
    }
    int pos = -1;
    for (int i = 0; i < 120; i++) {
        if (ans[i] == 1) {
            pos = i;
            break;
        }
    }
    for (int i = 1; i <= 2*n-2; i++) {
        if (a[i][pos] == 1) {
            ans1 ^= a[i];
        } else {
            ans2 ^= a[i];
        }
    }
    if (decode(ans1) > decode(ans2)) swap(ans1, ans2);

    cout << decode(ans1) << "\n" << decode(ans2) << "\n";

    return 0;
}


posted @ 2025-06-19 17:20  Guaninf  阅读(5)  评论(0)    收藏  举报