문제 정의
정수 n개가 담긴 배열 nums가 주어졌다고 가정해 봅시다. 이때 배열 안의 숫자들이 쌍별 서로소(pairwise coprime)인지, 집합별 서로소(setwise coprime)인지, 아니면 서로소가 아닌지 판별해야 합니다.
쌍별 서로소(pairwise coprime): 두 수 nums[i]와 nums[j]의 최대공약수가 gcd(nums[i], nums[j]) = 1일 때 이 두 수는 서로소입니다. 배열 내 모든 숫자 쌍(i < j)에 대해 이 조건이 성립해야 합니다.
집합별 서로소(setwise coprime): 배열 전체 숫자들의 최대공약수가 1일 때 집합별 서로소라고 합니다.
두 조건 중 어느 것도 만족하지 않으면 서로소가 아님(not coprime)이라고 합니다.
예를 들어 n = 4, nums = {7, 11, 13, 17}이 입력으로 주어지면 출력은 "숫자들은 쌍별 서로소입니다"가 됩니다. 배열의 모든 숫자 쌍을 검사해 보면 최대공약수가 항상 1이기 때문입니다.
접근 방법
이 문제는 다음 단계를 따라 해결할 수 있습니다.
크기가 100이고 0으로 초기화된 배열 fac을 정의한다.
크기가 100이고 0으로 초기화된 배열 checkPrime을 정의한다.
gcdVal := 0
i := 0부터 i < n까지 반복하며(i는 1씩 증가):
gcdVal := gcd(nums[i], gcdVal)
fac[nums[i]] 값을 1 증가
만약 gcdVal이 1과 같다면:
pw := true
k := 2부터 k < 100까지 반복하며(k는 1씩 증가):
checkPrime[k]가 참이면 다음 반복으로 건너뛴다
c := 0
j := k부터 j < 100까지 j := j + k씩 증가하며:
c := c + fac[j]
checkPrime[j] := true
c <= 1이면 pw는 true를 유지
pw가 참이면:
"The numbers are pairwise coprime" 출력
그렇지 않으면:
"The numbers are setwise coprime" 출력
그렇지 않으면:
"The numbers are not coprime" 출력
동작 원리
이 알고리즘은 크게 두 단계로 동작합니다. 먼저 배열의 모든 숫자에 대한 최대공약수를 누적으로 계산하여, 그 값이 1이 아니면 즉시 "서로소가 아님"을 판정합니다. 최대공약수가 1이라면, 각 소수 k에 대해 k의 배수(2k, 3k, ...)에 해당하는 숫자가 배열에 몇 번 등장했는지 세어 봅니다. 특정 소수의 배수가 두 개 이상 존재하면 그 두 수의 최대공약수는 k 이상이 되므로 쌍별 서로소가 될 수 없습니다. 따라서 모든 소수에 대해 배수가 최대 한 번씩만 등장하면 쌍별 서로소이고, 전체 최대공약수는 1이지만 일부 소수의 배수가 겹친다면 집합별 서로소로 판정됩니다.
C++ 구현 예제
아래 구현 예제를 통해 더 자세히 이해해 보겠습니다.
#include <bits/stdc++.h>
using namespace std;
void solve(int n, int nums[]){
int fac[100] = {0};
bool checkPrime[100] = {0};
int gcdVal = 0;
for(int i = 0; i < n ; i++) {
gcdVal = __gcd(nums[i], gcdVal);
++fac[nums[i]];
}
if(gcdVal == 1) {
bool pw = true;
for(int k = 2; k < 100; ++k) {
if(checkPrime[k])
continue;
int c = 0;
for(int j = k; j < 100; j += k) {
c += fac[j];
checkPrime[j] = true;
}
pw = pw && c <= 1;
}
if(pw)
cout<< "The numbers are pairwise coprime";
else
cout<< "The numbers are setwise coprime";
}
else
cout << "The numbers are not coprime";
}
int main() {
int n = 4, nums[] = {7, 11, 13, 17};
solve(n, nums);
return 0;
}
입력
4, {7, 11, 13, 17};
출력
The numbers are pairwise coprime