Codeforces Round #742 (Div. 2)-B. MEXor Mixup

falconlee236

·

2021. 11. 16. 20:26

반응형

문제 설명

엘리스는 밥에게 두 정수 ab(a>0,b0) 를 제시했다. 호기심 많은 소년인 밥은 모든 음이 아닌 정수를 원소로 가지는 배열의 모든 원소의 MEX 값이 a이고, 배열의 모든 원소의 XOR 값이 b를 만족하는 배열을 만들었다.

밥이 적은 가능한 최소길이를 가진 배열은 무엇일까?

배열의 MEX(Minimum EXcluded)는 배열의 원소가 아닌 값 중에서 가장 작은 음이 아닌 정수를 말하고, 배열의 XOR은 배열의 모든 원소를 XOR 비트 연산을 한 값을 말한다.

Input
첫번째 줄에는 테스트 케이스의 개수 t가 주어진다. (1t5104)

각 테스트케이스는 각각 배열의 MEX 값과 XOR 값을 나타내는 두 정수 ab(1a3105,0b3105) 가 주어진다.

Output
각 테스트 케이스마다 배열의 MEX 값이 a이고, XOR 값이 b인 가장 작은 배열의 길이를 나타내는 정수 하나를 출력한다. 그리고 그러한 답이 존재하는 테스트케이스만 주어진다.

Example
input
5
1 1
2 1
2 0
1 10000
2 10000

output
3
2
3
2
3

문제 접근

사용한 알고리즘: 비트마스킹, 구현
걸린 시간 : 00:20
이 문제는 구현이 어려운게 아니라 이 MEX라는 값의 개념을 모르면 그냥 풀수가 없다. 나도 이 문제를 풀면서 MEX라는 개념을 처음 알았는데, 다음과 같다. 배열에 들어있는 원소가 음이 아닌 정수를 만족한다고 가정할 때, 배열에 있는 원소가 아닌 정수 중에서 가장 작은 값을 말한다.

이렇게만 적으면 당최 뭔 소린지 전혀 이해할 수 없다. 그렇기 때문에 예시를 들어서 설명을 하자.
배열 a[0,3,4,6,20,10101010101] 라고 할때, a의 MEX는 뭘까? 답은 1이다.
a[0,1,2,3,4,5,6,101203124,6435645335345] 라고 할때, a의 MEX는 뭘까? 답은 7이다.
첫번째 예시에서는 배열 a에 없는 원소를 오름차순으로 적어보자면 1,2,5,7,8,9,10,11 이다. 이 값중에서 가장 작은 값이 바로 1이기 때문에 답이 1이다.
두번째 예시에서는 배열 a에 없는 원소를 오름차순으로 적어보자면 7,8,9,10,11,12,13,14 이다. 이 값중에서 가장 작은 값이 바로 7이기 때문에 답이 7이다.

이정도면 MEX값은 완벽히 이해했을 것이라고 믿는다. 그러면 MEX값이 a가 되기 위해서는 배열을 어떻게 구성하면 최소 길이로 만들 수 있을까? 배열에 없는 원소중에서 가장 작은 값이 a가 되면 된다. 즉 배열을 [0,1,2,,a2,a1] 이렇게 구성한다면 MEX의 값이 a 가된다. 즉 MEX가 a가 되기 위해서 필요한 최소 배열의 길이는 a이다.

XOR값은 그냥 모든 배열의 XOR값을 계산하면 되는데, 계산의 편의를 위해서 a의 최대값인 300000 까지의 bitwise XOR값을 계산하자. 왜냐하면 MEX값이 a 이면 반드시 배열의 구성이 [0,1,2,,a2,a1] 이렇게 되어야 한다는 것을 알았기 때문이다. 정답 코드에 있는 dp[i]는 0 부터 i 까지의 bitwise XOR값을 계산해 놓았다. 그리고 bitwise XOR 연산의 성질 3가지를 알아두자.

  1. A0=A
  2. AA=0
  3. A(BC)=(AB)C

그렇다면 이 값을 왜 계산해 뒀을까? 문제 풀이에 반드시 필요한 값이기 때문이다. 출력값이 a, b이고 0 부터 a1 까지 XOR한 값을 k 라고 하자. 이때 나올 수 있는 경우가 총 3가지 있다.

  1. b=k: 모든 경우를 그냥 만족하기 때문에 배열에 추가로 원소를 삽입할 필요가 없다. 이 때 배열의 길이는 a
  2. bk인 경우, 두가지 경우가 추가로 존재한다.
    • bka:인 경우 bk 값이 a가 아니므로 배열에 bk 를 추가하면 된다. 그러면 k(kb)=b 이므로 문제 조건을 만족한다. 이때 배열의 길이는 a+1 이다.
    • bk=a:인 경우 bk 값이 a이므로 배열에 bk 를 추가 할 수 없다. 추가하면 MEX값이 a가 아니게 되기 때문이다. 그래서 우회하는 방법을 써야하는데, 이것 또한 bitwise XOR연산의 성질을 사용한다. 임의의 매우 큰 수를 d라고 하자. k(kbd)d=b 이므로 배열에 kbdd 을 추가하면 되므로 이때 배열의 길이는 a+2 이다.

정답 코드

#include <cstdio>

int dp[300001];

int main(){
    for(int i = 1; i <= 300000; i++) dp[i] = (dp[i - 1] ^ i);
    int t; scanf("%d", &t);
    while(t--){
        int a, b; scanf("%d %d", &a, &b);
        int k = dp[a - 1];
        if(k == b) printf("%d\n", a);
        else{
            if((k ^ b) != a) printf("%d\n", a + 1);
            else printf("%d\n", a + 2);
        }
    }
}
반응형