https://www.acmicpc.net/problem/1437
풀이가 2가지가 있다.
1. Dp
2. 수학
1. 다이나믹 프로그래밍
Dp로 풀려고 하면 당연히 점화식을 찾아야 하고 노가다를 하다보면 점화식이 쉽게 찾아진다.
n > 4인 경우에서 dp[n] = dp[n-3]*3이 된다.
#include <iostream>
#define mod 10007
using namespace std;
int main() {
int n;
cin >> n;
int* arr = new int[n+1];
arr[0] = 0;
arr[1] = 1;
arr[2] = 2;
arr[3] = 3;
arr[4] = 4;
for(int i = 5; i <= n; i++){
arr[i] = (arr[i-3] * 3) % mod;
}
cout << arr[n];
}
2. 수학
수학적 접근이 쉽지 않은데... 결론적으로는 3을 가장 많이 만들면 된다.
DP로 접근할때 노가다한 수들을 소인수 분해 해보면 전부다 2와3으로 표현될 수 있으며, 3이 최대로 들어가고 부족한 경우 2를 사용했다. (단, 10 = 3+3+3+1과 같이 1이 등장하는 경우는 3을 하나 지우고 2²을 넣어주면 된다)
3을 최대로 많이 사용하는건 n의 n제곱근의 최댓값을 구해보면 된다.(미분해서 = 0 으로 극댓값 찾으면 됨.)
그러면 최댓값을 만드는 n이 자연상수 e가 된다. 따라서 e(2.718xx..)에 가까운 3이 자연수 중에서 가장 커지게 하는 값이다. (사실 가깝다고 하면 안되고 함수를 그려보면 f(2) < f(3)이며 e에서 극댓값을 가진다.)
따라서 3을 최대로 쓰고 나머지를 2로 채우면 수를 구성하는 수들의 곱이 최대가 된다.
사실상 문제를 풀면서 제대로 된 증명을 하기엔 어렵고 관찰해서 발견하는게 낫다.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if(n == 0 || n == 1) {
cout << n;
return 0;
}
int mx, re, ans;
mx = n/3;re = n%3;
ans = 1;
if(re == 2) ans *= 2;
else if(re == 1) {
ans *= 4;
mx -= 1;
}
for(int i = 0; i < mx; i++){
ans *= 3;
ans %= 10007;
}
cout << ans;
}
'📚알고리즘 > 백준' 카테고리의 다른 글
[백준 31404번] 아리스, 청소합니다! (Easy) (C++) (0) | 2024.07.03 |
---|---|
[백준 2206번] 벽 부수고 이동하기 (C++) (0) | 2024.07.03 |
[백준 28703번] Double it (C++) (0) | 2024.06.23 |
[백준 20302번] 민트 초코 (C++) (0) | 2024.06.23 |
[백준 2048번] Hello, 2048! (0) | 2024.06.21 |