-
반응형
https://www.acmicpc.net/problem/14476
14476번: 최대공약수 하나 빼기
첫째 줄에 정수의 개수 N (4 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 N개의 수가 주어진다. 각각의 수는 20억을 넘지 않는 자연수이다.
www.acmicpc.net
풀이
먼저, 유클리드 호제법과 누적합의 개념을 이용하여 풀었다.
유클리드 호제법에 대해선 아래에 설명을 해놓았다.
[알고리즘] 최소공배수와 최대공약수 C++
0. 목차 최대공약수(Greatest Common Divisior) 의 개념 최대공약수 알고리즘 1 (시간복잡도 O( min(A ,B) ) ) 최대공약수 알고리즘 유클리드 호제법 (시간복잡도 O(logN)) 최소공배수(Lease Common Multiple)의..
khu98.tistory.com
먼저 gcd_left배열과 gcd_right 배열을 선언해주었다.
gcd_left[i] = 1번째 원소~i번째 원소까지 숫자들의 최대공약수를,
gcd_right[i] = i번째 원소~ N번째 원소까지 숫자들의 최대공약수를 저장해주었다.
그런뒤, 다음과 같은 방법을 사용했다.
k번째 숫자를 제거했을때의 최대공약수 = gcd ( gcd_left[k-1], gcd_right[k+1] )
k번째 숫자를 제거했을때, 좌측부분의 최대공약수와 우측부분의 최대공약수의 최대공약수를 구했을때, 원래보다 커지면 갱신을 해주었다.
이 동작을 첫번째 원소~마지막원소까지 실행해주어 갱신해준다.
시간복잡도
유클리드 호제법을 이용했으므로, gcd_left와 gcd_right를 셋팅하는데 O(NlogN)시간이 걸렸고,
k번째 숫자를 제거하는 알고리즘은 O(N)시간이 걸리므로, 총 시간복잡도는 O(NlogN)이 된다.
코드
#include <iostream> #include<algorithm> using namespace std; int gcd_left[1000001], gcd_right[1000001],arr[1000001]; int n; int gcd(int a, int b) { if (b == 0) { return a; } else { return gcd(b, a%b); } } int main() { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n; for (int i = 1; i <= n; i++) { cin >> arr[i]; if (i == 1) { gcd_left[i] = arr[i]; } if (i == n) { gcd_right[i] = arr[i]; } } for (int i = 2; i <= n; i++) { gcd_left[i] = gcd(arr[i], gcd_left[i - 1]); gcd_right[n - i+1] = gcd(arr[n - i+1], gcd_right[n - i+2]); } int maxValue = gcd_left[n]; int index = -1; for (int i = 1; i <= n; i++) { int g = gcd(gcd_left[i - 1], gcd_right[i + 1]); if (maxValue < g) { int now = arr[i]; if (arr[i] % g != 0) { maxValue = g; index = i; } } } if (index == -1) { cout << "-1\n"; } else { cout << maxValue << " " << arr[index]; } return 0; }
반응형'문제풀이 > 백준oj' 카테고리의 다른 글
[백준OJ] 6987번 월드컵 (0) 2021.08.14 [백준OJ] 9019번 DSLR (0) 2021.08.13 [백준OJ] 9079번 동전 게임 (0) 2021.08.11 [백준OJ] 16400번 소수 화폐 (0) 2021.08.10 [백준OJ] 3584번 가장 가까운 공통 조상 (0) 2021.08.09 댓글