PS

BOJ 24146 : 分数 (Fraction)

lickelon 2024. 7. 1. 22:54
  • 문제 링크 : boj.kr/24146
  • 난이도 : G3
  • 태그 : 우선순위 큐, 정수론
 

Baekjoon Online Judge

Baekjoon Online Judge 프로그래밍 문제를 풀고 온라인으로 채점받을 수 있는 곳입니다.

www.acmicpc.net


코드

#include <bits/stdc++.h>

#define all(x) (x).begin(), (x).end()

#define INF 0x7FFFFFFF

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll, ll>;

struct compare{
    bool operator()(pii &a, pii &b) {
        return a.first*b.second > b.first*a.second;
    }
};

ll gcd(ll a, ll b)
{
    if (!b) return a;
    return gcd(b, a % b);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int m, k;
    cin >> m >> k;
    priority_queue<pii, vector<pii>, compare> _pq;
    for(int i = 2; i <= m; i++) {
        _pq.push({1, i});
    }

    int idx = 1;
    while(!_pq.empty() && idx <= k) {
        pii curr = _pq.top(); _pq.pop();
        if(curr.first + 1 < curr.second) _pq.push({curr.first+1, curr.second});
        if(gcd(curr.first, curr.second) != 1) {
            continue;
        }
        if(idx == k) {
            cout << curr.first << " " << curr.second;
            return 0;
        }
        idx++;
    }

    cout << -1;
    return 0;
}

풀이

dong_gas의 글을 보고 풀게 되었다.

a/b < (a+1)/b는 당연하다. 이는 분수들을 작은 순서대로 확인할 때 아직 a/b를 확인하지 않았다면 (a+1)/b는 고려할 필요도 없다는 것을 의미한다.

따라서 동시에 봐야할 분수들의 수는 최대 M개이다.

동시에 보고 있는 분수들 중 가장 작은 분수를 골라내기 위해 우선순위 큐를 사용한다.

이때 기약분수가 아닌 분수들도 보게 될 텐데, 분자와 분모의 gcd를 확인하여 1이 아니라면 그대로 넘긴다.

 

처음 M개의 분수를 우선순위 큐에 넣는데에 O(MlogM), M개의 분수들 중 가장 작은 기약분수를 K번 확인하는데에 O(KlogMlogM)이므로 총 시간복잡도는 O((M+KlogM)logM)이다.

'PS' 카테고리의 다른 글

BOJ 23889 : 돌 굴러가유  (0) 2024.07.03
BOJ 1052 : 물병  (0) 2024.07.02
BOJ 2513 : 통학버스  (1) 2024.06.30
BOJ 13019 : A를 B로  (0) 2024.06.29
BOJ 27923 : 햄버거최대 몇개드실수있나요?  (0) 2024.06.28