알고리즘/알고리즘 이론

포함 배제의 원리 (Inclusion-Exclusion Principle)

GaeunLee 2023. 10. 23. 00:45

 

 

포함 배제의 원리 (Inclusion-Exclusion Principle)

포함 배제의 원리는 조합론에서 합집합의 크기를 구할 때 사용하는 공식이다.

 

 

그렇다면 합집합의 크기(원소의 개수)를 구하는 방법을 알아보자.

 

위 그림에서 합집합의 크기를 구하는 방법은 다음과 같다.

$$n(A\cup B\cup C) = n(A) + n(B) + n(C) - \{n(A\cap B) + n(B\cap C) + n(C\cap A)\} + n(A\cap B\cap C)$$

 

 

이를 일반화하면 다음과 같은 식이 성립한다.

 

전체집합의 모든 부분집합의 교집합의 원소를 더하거나 뺄 때, 부분집합의 수가 홀수라면 더하고, 짝수라면 뺀다.

 

문제

소수의 배수 (BOJ 17436)

https://www.acmicpc.net/problem/17436

 

17436번: 소수의 배수

첫째 줄에 N(1 ≤ N ≤ 10)과 M(1 ≤ M ≤ 1012)이 주어진다. 둘째 줄에는 N개의 소수가 주어진다. 입력으로 주어지는 소수는 100보다 작거나 같으며, 같은 소수가 두 번 이상 주어지지 않는다.

www.acmicpc.net

코드

더보기
#include <iostream>
#include <cmath>
#include <vector>
typedef long long ll;
using namespace std;

ll n, m, tmp;
vector<ll> v;

int main() {
	cin.tie(0); cout.tie(0);
	ios_base::sync_with_stdio(false);

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		cin >> tmp;
		v.push_back(tmp);
	}

	ll sum = 0;

    // 비트마스킹으로 부분집합 구하기
	for (int i = 1; i < (1<<n); i++) {
		ll lcm = 1;
		int odd = -1;
		for (int j = 0; j < n; j++) {
			if (i & (1<<j)) { 
				odd *= -1;
				lcm *= v[j];
			}
		}
		sum += odd * (m / lcm);
	}
	
	cout << sum;
	return 0;
}