알고리즘 연습/백준
[BOJ 3343 장미] 정수론, LCM
_h.j
2024. 4. 25. 17:17
728x90
- $N =10^15$ 크다. 완탐하면 시간 초과 발생.
- 접근의 핵심은 두 수 a,b의 최소공배수 개념
접근법
최소공배수를 찾을 필요는 없지만 최소 공배수 개념을 활용해서 묶음의 가성비를 구한다.
A : 2 개 → 3원 X 10
B : 10개 → 14원 X 2
A : 20개 → 30원
B : 20개 → 28원 win
묶음의 가성비는 B가 더 좋다.
A의 묶음 개수 x, B의 묶음 개수 y라 할때
만약, 총 x*y(최소공배수) 개를 사야한다면 B를 x개 사는 것이 더 이득이다.
B를 x개 사는 게 더 이득이다. ==> A를 y개 이상 살 필요가 없다. (y-1개 이하일 땐 아니란 의미)
그러니 B에 묶음 가성비 좋은 가게로 설정해두고
A를 y개 미만일 때까지 가격을 비교하면 된다.
코드
#include <iostream>
#include <climits>
#include <cmath>
using namespace std;
typedef long long ll;
ll N, ans = LONG_MAX;
ll na, nb, ca, cb; // 묶음개수 ,가격
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N >> na >> ca >> nb >> cb;
//묶음 가성비 B가 더 좋게 설정
if (ca * nb < cb * na) {
ll tmp = na;
na = nb;
nb = tmp;
tmp = ca;
ca = cb;
cb = tmp;
}
//정확하게 따지면 cb가 아니라 최소공배수 만드는 배수겠지만
// nb로 해도 답은 나오니까
// x : a의 묶음 개수
// y: b의 묶음 개수
for (ll x = 0; x < nb; x++) {
ll y = (long long)ceil((double)(N - na * x) / (double)nb);
bool over = false;
if (y < 0) {
y = 0;
over = true;
}
ans = min(ans, ca * x + cb * y);
if (over) break;
}
cout << ans <<"\n";
return 0;
}
참고
https://velog.io/@alswndit/%EB%B0%B1%EC%A4%80-3343%EB%B2%88-%EC%9E%A5%EB%AF%B8-G4
728x90