티스토리 뷰

문제

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

 

풀이

 

문제풀이를 완전탐색 알고리즘으로 생각을 해보면 1~N까지의 수를 하나씩 다 빼보고 그 중에 가장 큰 최대공약수를 가질 수 있는 수를 빼는 것입니다.

하지만 완전탐색의 경우 1~N까지 숫자를 빼는 것과 숫자를 뺀 나머지 수들의 최대공약수를 구하는 과정에 있어서 시간초과가 발생할 것이라고 생각 했습니다.

 

제 풀이는 1부터 N까지 모두 빼보는 것까지는 완전탐색과 똑같은 방법입니다.

다른 점은 Segement Tree 를 이용해서 1~N까지의 최대공약수를 미리 저장해놓는 것입니다.

현재 숫자를 빼고 Segement Tree를 Update 해주고 비교해주는 거라고 보시면 됩니다.

 

소스코드

 

#include <iostream>
#include <algorithm>

using namespace std;

const int MAX_N = 1e6;

int nums[MAX_N+1];
long long int segmentTree[MAX_N * 4];
bool flag;

long long int getIdx(long long int n){

    long long int ret = 1;

    while( ret < n){
        ret*=2;
    }

    return ret;
}

long long int gcd(long long int a, long long int b){
    return b == 0 ?  a : gcd(b,a%b);
}

void initialize(long long int firstIdx,int n){

    for(int i = firstIdx; i < firstIdx + n; i++){
        segmentTree[i] = nums[i-firstIdx];
    }

    for(int i = firstIdx-1;i >= 1; i--){
        segmentTree[i] = gcd(segmentTree[i*2], segmentTree[i*2+1]);
    }
}

void updateSegmentTree(long long int firstIdx, long long int updateIdx, long long int delta){

    long long tmpIdx = firstIdx+updateIdx;
    segmentTree[tmpIdx] = delta;
    while(tmpIdx >= 1){

        tmpIdx/=2;
        segmentTree[tmpIdx] = gcd(segmentTree[tmpIdx*2], segmentTree[tmpIdx*2+1]);
    }
}

pair<long long int, long long int> getAnswer(long long int firstIdx, int n){

    pair<long long int, long long int> ret = {segmentTree[1], nums[0]};
    
    int cnt = 0;
    for(int i = 0;i < n; i++){
        
        long long int curNum = nums[i];

        // 현재 숫자 제외
        updateSegmentTree(firstIdx, i, 0);

        // 나머지들의 최대공약수가 뺀 수의 약수인 지 판별
        if(nums[i]%segmentTree[1] != 0 && ret.first < segmentTree[1]){

            ret = {segmentTree[1], nums[i]};
        }

        if(nums[i] % segmentTree[1] == 0)
            cnt++;

        updateSegmentTree(firstIdx,i,curNum);
    }

    // 불가능한 경우
    if(cnt == n)
        flag = true;
        
    return ret;
}

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;

    cin >> n;

    for(int i = 0; i < n; i++){
        
        cin >> nums[i];
    }

    long long int firstIdx = getIdx(n);

    initialize(firstIdx, n);

    pair<long long int, long long int> answer = getAnswer(firstIdx,n);

    if(flag){
        cout << -1 << "\n";
    }
    else{
        cout << answer.first << " " << answer.second << "\n";
    }

    return 0;
}

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2170번 선 긋기  (0) 2020.02.06
[백준] 7806번 GCD!  (0) 2019.11.12
[백준] 6569번 몬드리안의 꿈  (1) 2019.11.05
[백준] 11727번 2xn 타일링 2  (0) 2019.11.04
[백준] 1563번 개근상  (0) 2019.11.04
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함