본문 바로가기
BOJ

백준 [C 언어] 1822: 차집합

by 횰임 2022. 2. 15.

✅ 비트 벡터 집합 사용

#include <stdio.h>

typedef unsigned long BitSet; 
//비트벡터집합의 자료형 (unsigned long)

#define BitSetNull (BitSet)0  
//공집합(모든 비트가 0)
#define BitSetBits 32   
//유효 비트 수 
#define SetOf(no) ((BitSet)1 << (no)) 
//원소가 no인 집합 {no} : 가장 아래쪽 비트 값이 1인 집합 {0} 에서 비트를 왼쪽으로 no만큼 shift

/*집합 s에 원소 n있는지 확인*/
int IsMember(BitSet s, int n)
{
  return s & SetOf(n);  //집합 s와 집합 {n}의 논리곱 연산 : 0이면 
}

/*집합 s에 n 추가*/
void Add(BitSet *s, int n)
{
  *s |= SetOf(n); //{n} 과  집합s 비트 or연산해서 없으면 추가되고 있으면 변함x
}

/*집합 s에 n 삭제*/
void Remove(BitSet *s, int n)
{
  *s &= ~SetOf(n);  //있으면 삭제되고 없으면 변함X
}

/*집합 s의 원소 개수(1인 것들의 개수) 반환*/
int Size(BitSet s)
{
  //s-1하면 s에서 첫 1이 나올 때까지 하위 비트들이 0->1로 바뀌고 첫 1비트는 1->0으로 바뀜. 따라서 s와 s-1을 비트AND연산 하면 ==> 첫 1비트가 0비트로 바뀌는 것. 
  //이때마다 카운트하면 그게 1비트 개수임.
  int n = 0;  //원소 개수
  for(; s != BitSetNull; n++) //공집합될 때까지 반복
  {
    s &= s-1;
  }
  return n;
}

/*집합 s의 모든 원소 출력*/
void Print(BitSet s)
{
  int i;
  //printf("{ ");
  for(i=0; i < BitSetBits; i++) //전체 32비트 돌면서
  {
    if(IsMember(s, i)) //i라는 원소가 존재하면 그 원소 출력
      printf("%d ", i);
  }
  //printf("}");
}

/*집합 s의 모든 원소 출력(줄바꿈 문자 포함)*/
void PrintLn(BitSet s)
{
  Print(s);
  putchar('\n');
}


int main(void) {

  int i;
  int data;
  //공집합으로 초기화
  BitSet sA = BitSetNull;
  BitSet sB = BitSetNull; 

  int An, Bn;
  scanf("%d %d", &An, &Bn);

  for(i=0; i<An; i++)
    {
      scanf("%d", &data);
      Add(&sA, data);
    }
  for(i=0; i<Bn; i++)
    {
      scanf("%d", &data);
      Add(&sB, data);
    }

  if(Size(sA & ~sB) == 0)
  {
    printf("0");
  }
  else{
    printf("%d\n", Size(sA & ~sB));
    PrintLn(sA & ~sB);
  }
  

  return 0;
}

❓틀렸습니다

어디서 틀린거지 출력 결과는 잘 나왔는데 반례를 한 번 찾아봐야겠다..

'BOJ' 카테고리의 다른 글

백준 [C언어] 1759 : 암호 만들기  (0) 2022.02.17
백준 [C언어] 11723 : 집합  (0) 2022.02.16
백준 [C언어] 18870 : 좌표 압축  (0) 2022.02.10
백준 [C언어] 1431 : 시리얼 번호  (0) 2022.02.10
백준[C언어] 2108: 통계학  (0) 2022.02.09