집합 \(S=\{x_1,\dots,x_n\}\)가 인수(약수)에 대해 닫혀있다는 조건 덕분에, \(A_{ij}=\gcd(x_i,x_j)\)로 만든 GCD 행렬의 행렬식이 놀랍게도
\[ \det(A)=\prod_{x\in S}\varphi(x) \]로 떨어진다. (Smith 정리)
문제 정보
문제 요약:
- \(S=\{x_1,\dots,x_n\}\)는 인수에 대해 닫힌 집합: \(x\in S\)이면 \(x\)의 모든 약수도 \(S\)에 포함
- GCD 행렬 \(A_{ij}=\gcd(x_i,x_j)\)의 행렬식 \(\det(A)\)를 구한다.
- 답은 \(1{,}000{,}000{,}007\)로 나눈 나머지
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 128MB
- 테스트 케이스 \(T\)
- \(0 < n < 1000\)
- \(0 < x_i < 2\cdot 10^9\), \(x_i\)는 정수
입출력 예제
입력 1:
| |
출력 1:
| |
핵심 관찰
관찰 1: \(\gcd\)는 오일러 피함수의 “약수 합”으로 표현된다
잘 알려진 항등식:
\[ \gcd(a,b)=\sum_{d\mid a,\ d\mid b}\varphi(d) \]이다. (산술함수 관점에서 \(\sum_{d\mid n}\varphi(d)=n\)을 이용하면 증명 가능)
관찰 2: GCD 행렬은 \(B\operatorname{diag}(\varphi)B^\top\)로 분해된다
집합 \(S\)가 인수에 대해 닫혀 있으므로, \(S\)의 원소들은 “약수 관계”로 부분순서를 이룬다. 여기서 \(B\)를
\[ B_{i,j}=\begin{cases} 1 & x_j \mid x_i\\ 0 & \text{otherwise} \end{cases} \]로 정의하면,
\[ A_{i,k}=\gcd(x_i,x_k)=\sum_{j=1}^{n} B_{i,j}\,\varphi(x_j)\,B_{k,j} \]가 되어
\[ A = B\cdot \operatorname{diag}(\varphi(x_1),\dots,\varphi(x_n))\cdot B^\top \]를 얻는다.
관찰 3: 인수-닫힘 조건 때문에 \(\det(B)=1\)
원소들을 “약수 \(\to\) 배수” 순서(즉 \(x_u\mid x_v\)면 \(u\le v\))로 정렬할 수 있다. 이 순서에서 \(B\)는 대각 원소가 1인 하삼각 행렬이 되므로
\[ \det(B)=1 \]이다.
따라서
\[ \det(A)=\det(B)\cdot \prod_{i=1}^{n}\varphi(x_i)\cdot \det(B^\top) = \prod_{i=1}^{n}\varphi(x_i) \]가 된다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력 T"] --> B["각 테스트 케이스 입력 n, x1..xn"]
B --> C["ans = 1 초기화"]
C --> D["각 x에 대해 φ(x) 계산 (소인수분해)"]
D --> E["ans = ans * φ(x) mod M"]
E --> F["ans 출력"]
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(n\cdot \pi(\sqrt{X}))\) | \(X\le 2\cdot 10^9\), 소수 리스트로 trial division |
| 공간 복잡도 | \(O(\pi(\sqrt{X}))\) | 소수 테이블 |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| 중복 원소 | “집합” 조건 위반 시 동일 행/열 발생 | 입력에 중복이 있으면 행렬식 0 (선택적으로 체크) |
| 큰 수 | \(x_i\)는 최대 \(2\cdot 10^9\) | \(\sqrt{x}\)까지 소인수분해, int64 사용 |
| 모듈러 곱 오버플로우 | \(1e9+7\)에서 곱 | long long로 곱 후 %MOD |
구현 코드
C++
| |
참고 문헌 및 출처
- 백준 3752번: 최대공약수 행렬식
- Smith, H. J. S. (1875). “On the value of a certain arithmetical determinant”
![Featured image of post [Algorithm] C++ 백준 3752번: 최대공약수 행렬식](/post/algorithm/2025-12-20-boj-3752-gcd-matrix-determinant-cpp-solution/wordcloud_hu_794a5af6a1251dd8.png)
![[Algorithm] C++ 백준 17372번: 피보나치 수의 최대공약수의 합](/post/algorithm/2025-12-20-boj-17372-fibonacci-gcd-sum-cpp-solution/wordcloud_hu_94c5bd100eedf3e2.png)
![[Algorithm] C++ 백준 32231번: 재우의 삼수강](/post/algorithm/2025-12-20-boj-32231-jaewoos-third-retake-hyperbolic-geometry-cpp-solution/wordcloud_hu_6b5d9f28adedfd92.png)
![[Algorithm] C++ 백준 3752번: 최대공약수 행렬식](/post/algorithm/2025-12-20-boj-3752-gcd-matrix-determinant-cpp-solution/wordcloud_hu_1490cf2b4f293afc.png)
![[Algorithm] C++ 백준 1185번: 유럽여행](/post/algorithm/2025-12-19-boj-1185-europe-travel-mst-kruskal-cpp-solution/wordcloud_hu_a7973902548ef27b.png)
![[Algorithm] C++ 백준 13324번: BOJ 수열 2](/post/algorithm/2025-12-19-boj-13324-boj-sequence-2-cpp-solution/wordcloud_hu_5564e49074c47ebd.png)
![[Algorithm] C++/Python 백준 13926 gcd(n, k) = 1 — φ(n) 계산](/post/algorithm/2025-10-14-boj-13926-gcd-n-k-equals-1-cpp-python-solution/wordcloud_hu_4f80697d0be61606.png)
![[Algorithm] C++ 백준 13618번: RSA](/post/algorithm/2025-12-12-boj-13618-rsa-cpp-solution/wordcloud_hu_ef9169c0740863be.png)
![[Algorithm] C++ 백준 9817번 : Necklace of Beads](/post/algorithm/2025-12-12-boj-9817-necklace-of-beads-cpp-solution/wordcloud_hu_fa5ee40dd060419.png)
![[Algorithm] C++ 백준 8464번: Non-Squarefree Numbers](/post/algorithm/2025-10-14-boj-8464-non-squarefree-numbers-cpp-solution/wordcloud_hu_4f80697d0be61606.png)