※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 2758번 문제인 로또이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/2758
2758번: 로또
선영이는 매주 엄청난 돈을 로또에 투자한다. 선영이가 하는 로또는 1부터 m까지 숫자 중에 n개의 수를 고르는 로또이다. 이렇게 열심히 로또를 하는데, 아직까지 한 번도 당첨되지 않은 이유는
www.acmicpc.net
idx 이상의 수를 가장 작은 수로 하면서 cnt개의 수를 고를 수 있는 경우의 수를 dp[idx][cnt]와 같이 나타내자.
이 때, dp[idx][cnt] = dp[idx*2][cnt-1] + dp[idx+1][cnt]와 같은 형태의 점화관계가 있음을 알 수 있다. 단, cnt=1의 경우는 dp[idx][cnt] = M-idx+1로 계산해주자. (초기값)
위의 점화식과 적절한 memoization을 이용해 문제를 해결하자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int T;
int N, M;
bool possible(int idx, int cnt) {
while (cnt > 1) idx <<= 1, cnt--;
return idx <= M;
}
ll dp[11][2001];
int visited[11][2001];
ll func(int idx, int cnt) {
if (visited[cnt][idx]) return dp[cnt][idx];
visited[cnt][idx] = 1;
if (cnt == 1) return dp[cnt][idx] = (M - idx + 1);
int vidx = idx;
ll ret = 0;
while (possible(vidx, cnt)) {
ret += func(vidx * 2, cnt - 1);
vidx++;
}
return dp[cnt][idx] = ret;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> T;
while (T--) {
memset(visited, 0, sizeof(visited));
cin >> N >> M;
cout << func(1, N) << '\n';
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 15724 // C++] 주지수 (0) | 2022.12.17 |
---|---|
[BOJ 2756 // C++] 다트 (1) | 2022.12.17 |
[BOJ 6841 // C++] I Speak TXTMSG (0) | 2022.12.17 |
[BOJ 26332 // C++] Buying in Bulk (1) | 2022.12.17 |
[BOJ 6840 // C++] Who is in the middle? (0) | 2022.12.17 |