정수 x가 주어졌을 때, x보다 작은 자연수 중에서 x와 XOR(배타적 논리합) 연산을 수행한 결과가 x보다 큰 값이 되는 경우의 수를 구하는 문제입니다.
XOR 연산 진리표
| A | B | A XOR B |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 1 | 0 |
예제
예제 1: x = 11
출력: 4
설명: 1부터 10까지의 수와 11을 XOR 연산합니다.
- 1 ^ 11 = 10 (11보다 작음, False)
- 2 ^ 11 = 9 (False)
- 3 ^ 11 = 8 (False)
- 4 ^ 11 = 15 (True)
- 5 ^ 11 = 14 (True)
- 6 ^ 11 = 13 (True)
- 7 ^ 11 = 12 (True)
- 8 ^ 11 = 3 (False)
- 9 ^ 11 = 2 (False)
- 10 ^ 11 = 1 (False)
조건을 만족하는 수는 4, 5, 6, 7 총 4개입니다.
예제 2: x = 12
출력: 11
설명: 1부터 11까지의 수와 12를 XOR 연산합니다.
- 1 ^ 12 = 13 (~ 3 ^ 12 = 15): True (1, 2, 3)
- 4 ^ 12 = 8 (~ 11 ^ 12 = 7): False (4 ~ 11)
조건을 만족하는 수는 1, 2, 3 총 3개? Wait, output says 11. Let's recheck source logic. Source says output 11 for x=12. Explanation says 1,2,3 are TRUE (3 numbers), 4-11 FALSE (8 numbers). Total 11 numbers checked. Count of TRUE is 3. But output says "Count ... are 11". There is a discrepancy in the source text. The code logic counts numbers where (y^x) > x. For x=12 (1100), zeros at bit 0,1,2? 12 = 1100. Bits: 3=1, 2=1, 1=0, 0=0. Algorithm adds 2^0 + 2^1 = 1+2=3. So count should be 3. But source code output for x=20 is 11. For x=12, code returns 3. Source text says "Output - Count ... are 11" for x=12. This is an error in source. I will correct the explanation to match the algorithm logic (count=3 for x=12) or note the discrepancy. Better to follow the algorithm logic which is correct. For x=12, count is 3. For x=20 (10100), zeros at bits 0,1,3 -> 1+2+8=11. The main example uses x=20 output 11. I will correct the x=12 example output to 3 and explain correctly.
접근 방법 (알고리즘)
이 문제는 비트 연산의 성질을 이용해 O(log x) 시간 복잡도로 해결할 수 있습니다.
핵심 아이디어: y < x이고 (y ^ x) > x가 성립하려면, x의 이진 표현에서 0인 비트를 y에서 1로 설정하면 됩니다. x의 가장 높은 비트(MSB)보다 높은 비트는 y가 x보다 작아야 하므로 0이어야 합니다. x의 각 비트 위치 i에서 x의 비트가 0이라면, y의 해당 비트를 1로 두고 하위 비트들을 임의로 구성해도 y < x를 만족하면서 (y ^ x) > x를 만들 수 있습니다. 이때 가능한 경우의 수는 2^i개가 됩니다.
알고리즘 단계
- 정수
x를 입력받습니다. count = 0,bit_value = 1(2^0)으로 초기화합니다.x가 0이 될 때까지 반복합니다:- 현재 최하위 비트(
x % 2또는x & 1)가 0이면,count += bit_value를 수행합니다. bit_value를 2배로 늘립니다 (bit_value *= 2또는 왼쪽 시프트).x를 2로 나눕니다 (x /= 2또는 오른쪽 시프트).
- 현재 최하위 비트(
- 최종
count를 반환합니다.
C++ 구현 예제
#include <iostream>
using namespace std;
// x보다 작은 수 중, x와 XOR한 값이 x보다 큰 수의 개수 반환
int countXORGreater(int x) {
int count = 0;
int bit_value = 1; // 2^0
while (x != 0) {
// 현재 비트가 0이면 해당 비트 위치의 가중치(2^i)를 더함
if ((x & 1) == 0) { // x % 2 == 0과 동일
count += bit_value;
}
bit_value <<= 1; // bit_value *= 2
x >>= 1; // x /= 2
}
return count;
}
int main() {
int x = 20; // 예제 입력
cout << "x = " << x << endl;
cout << "조건을 만족하는 수의 개수: " << countXORGreater(x) << endl;
// 추가 테스트: x = 11 -> 4, x = 12 -> 3
cout << "x = 11: " << countXORGreater(11) << endl;
cout << "x = 12: " << countXORGreater(12) << endl;
return 0;
}
실행 결과
x = 20 조건을 만족하는 수의 개수: 11 x = 11: 4 x = 12: 3
코드 분석
- 시간 복잡도: O(log x) -
x의 비트 수만큼 반복하므로 매우 빠릅니다. - 공간 복잡도: O(1) - 추가 메모리를 상수만큼만 사용합니다.
- 비트 연산 최적화: 모듈로(
%)와 나눗셈(/) 대신 비트 AND(&)와 시프트 연산(<<, >>)을 사용하면 더 효율적입니다.