baekjoon

[백준] 13505 두 수 XOR

윤만석 2023. 6. 28. 16:27

문제

N개의 수가 주어졌을 때, XOR한 값이 가장 큰 두 수를 찾는 프로그램을 작성하시오.

즉, A1, A2, ..., AN 중에서 i ≠ j이면서 Ai XOR Aj 가 가장 큰 것을 찾아야 한다.

입력

첫째 줄에 N (2 ≤ N ≤ 100,000)이 주어진다.

둘째 줄에는 N개의 수가 주어진다. 입력으로 주어지는 수는 1,000,000,000보다 작거나 같은 음이 아닌 정수이다.

출력

첫째 줄에 XOR한 값이 가장 큰 두 수의 XOR한 결과를 출력한다.

 

주어지는 숫자들을 2진수로 바꾸고, 그 숫자들을 이용해 트라이를 구성합니다.

이때 그 숫자들의 길이를 맞춰주어야 합니다. 예를들어,,, 32 =10000 와 1=1이 있을때 트라이에

10000와 00001을 넣어야 합니다.

이런식으로 구성한 트라이에

각 숫자의 보수(complement)를 하나씩 넣어봅니다. 만약 00001=>11110을 넣을때 트라이에 순서대로 그 숫자가 존재하면 

string 에 1을 더하고 없으면 0을 더합니다.

그런식으로 만들어진 string이 XOR의 이진수입니다. 그 이진수의 최댓값을 출력하면 답입니다.

 

#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false),cin.tie(NULL);
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)

using namespace std;

typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = { -1,0,1,0 }, dx[] = { 0,1,0,-1 }, INF = 987654321;
char rev(char c) {
    if (c == '0')return '1';
    return '0';
}
struct Trie {
    bool output;
    Trie* go[2];
    Trie() {
        fill(go, go + 2, nullptr);
        output = false;
    }
    ~Trie() {
        rep(i, 2)
            if(go[i])
                delete go[i];
    }
    void insert(string str) {
        if (!str.length()) {
            output = 1;
            return;
        }
        int next = str[0] - '0';
        if (!go[next]) {
            Trie* newTrie = new  Trie;
            go[next] = newTrie;
        }
        go[next]->insert(str.substr(1));
    }
    string query(string str) {
        if (!str.length())return "";
        string ret;
        int cur = rev(str[0])-'0';
        if (go[cur]) {
            ret.push_back('1');
            ret.append(go[cur]->query(str.substr(1)));
        }
        else {
            ret.push_back('0');
            if (cur == 0) {
                ret.append(go[1]->query(str.substr(1)));
            }
            else {
                ret.append(go[0]->query(str.substr(1)));
            }
        }
        return ret;
    }
};
int N, maxlen = 1;
vector<string>strings;
int main() {
    FAST;
    cin >> N;
    rep(i, N) {
        int x;
        cin >> x;
        string str;
        int len = 1;
        while (x > 1) {
            str.push_back('0'+x % 2);
            x /= 2;
            len++;
        }
        maxlen = max(maxlen, len);
        if(x!=0)
            str.push_back('1');
        strings.push_back(str);
    }
    Trie* root = new Trie;
    for (string &str : strings) {
        int len = str.length();
        for (int i = 0; i < maxlen - len; i++) {
            str.push_back('0');
        }
        reverse(str.begin(), str.end());
        root->insert(str);
    }
    int ans = 0;
    for (string str: strings) {
        string temp = root->query(str);

        int val = 0;
        for (int i = 0; i < maxlen; i++) {
            if (temp[i] == '1') {
                val += pow(2, maxlen - 1 - i);
            }
        }
        ans = max(ans, val);
    }
    cout << ans;
}

'baekjoon' 카테고리의 다른 글

[백준] 1765 닭싸움 팀 정하기  (0) 2023.06.29
[백준] 16933 벽 부수고 이동하기 3  (0) 2023.06.29
[백준] 5670 휴대폰 자판  (0) 2023.06.28
[백준] 3073 집으로 가는 길  (0) 2023.06.27
[백준] 11670 초등 수학  (0) 2023.06.26