※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1750번 문제인 서로소의 개수이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1750
1750번: 서로소의 개수
예제 1의 경우 가능한 경우의 수는 (2, 3), (4, 3), (2, 4, 3)이다.
www.acmicpc.net
주어진 길이
선택한 원소가 서로소이게 원소를 고르는 경우의 수는 전체 경우의 수에서 선택한 원소가 서로소가 아니게 원소를 고르는 경우의 수를 빼는 것으로 구할 수 있다. 그 경우의 수는 10만 이하의 양의 정수 k에 대하여 주어진 원소들이 모두 k의 배수가 되도록 원소를 고르는 경우의 수를 구할 수 있다면 포제원리(inclusion and exclusion principle)와 뫼비우스 함수(möbius function)를 이용해 빠르게 계산해낼 수 있다. 전체 원소의 개수가 50, 즉 충분히 적은 수이므로 위에서 필요한 값은 주어진 원소 중 k의 배수의 개수를 직접 세는 것으로 충분히 빠르게 구할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
typedef long long ll;
char mobius[100001];
bool sieve[100001];
int N;
int arr[50];
ll ans;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
for (int i = 1; i < 100001; i++) mobius[i] = 1;
for (int i = 2; i < 100001; i++) {
if (sieve[i]) continue;
for (int j = i; j < 100001; j += i) {
mobius[j] *= -1;
sieve[j] = 1;
}
ll sq = (ll)i * i;
for (ll j = sq; j < 100001; j += sq) mobius[j] = 0;
}
cin >> N;
for (int i = 0; i < N; i++) cin >> arr[i];
ans = (1LL << N) - 1;
for (int i = 2; i < 100001; i++) {
int cnt = 0;
for (int j = 0; j < N; j++) {
if (arr[j] % i) continue;
cnt++;
}
ans += ((1LL << cnt) - 1) * mobius[i];
}
cout << ans % 10000003;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 2737 // C++] 연속 합 (1) | 2024.01.05 |
---|---|
[BOJ 7117 // C++] Sevens, twos and zeros (0) | 2024.01.04 |
[BOJ 2436 // C++] 공약수 (1) | 2024.01.02 |
[BOJ 4108 // C++] 지뢰찾기 (1) | 2024.01.01 |
[BOJ 2624 // C++] 동전 바꿔주기 (1) | 2023.12.31 |