문제 링크

정말 순수하게 비트 마스크 조작 연습 문제다. 각종 비트 마스크 조작의 Best-Practice들을 배워보자. 사소해 보여도 이런 단위 연산을 정형화해두는게 코드를 짤 때 도움이 많이 된다.

비트 연산 시 비트 연산자들의 연산 우선순위를 반드시 고려해 괄호를 쳐줘야 한다.

  1. 특정 비트 켜기
	bm |= (1 << (v - 1));

v번째 비트를 1로 바꾼다. 첫 비트의 인덱스는 1이다.

  1. 특정 비트 끄기
    bm &= ~(1 << (v - 1));
    v번째 비트를 0으로 바꾼다. 첫 비트의 인덱스는 1이다.
  2. 특정 비트 상태 확인
     if (bm & (1 << (v - 1)) {
     	printf("1");
     }
     if ((bm & (1 << (v - 1))) == 0) {
     	printf("0");
     }
    v번째 비트값을 확인한다. 첫 비트의 인덱스는 1이다.
  3. 특정 비트 상태 반전 ( 0이면 1로 변경, 1이면 0으로 변경 )
    bm ^= (1 << (v - 1));
    v번째 비트를 반전시킨다. 첫 비트의 인덱스는 1이다.
  4. 모든 비트 켜기
    mask = (1 << n) - 1; 
    bm = mask;
    n개의 비트를 가진 비트 마스크의 최대값은 이다.
  5. 모든 비트 끄기
    bm = 0;
    당연히 모든 비트 마스크의 최소값은 0이다.

코드

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
 
using namespace std;
 
int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	int bm = 0;
	const int mask = (1 << 21) - 1;
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		string op;
		cin >> op;
		int v;		
		if (op.compare("add") == 0) {
			cin >> v; v -= 1;
			bm |= (1 << v);
		}
		else if (op.compare( "remove") == 0) {
			cin >> v; v -= 1;
			bm &= ~(1 << v);
		}
		else if (op.compare( "check") == 0) {
			cin >> v; v -= 1;
			if (bm & (1 << v)) {
				printf("1\n");
			}
			else {
				printf("0\n");
			}
		}
		else if (op.compare( "toggle") == 0) {
			cin >> v; v -= 1;
			bm ^= (1 << v);
		}
		else if (op.compare( "all") == 0) {
			bm = mask;
		}
		else if (op.compare( "empty") == 0) {
			bm = 0;
		}
	}
}