www.codeup.kr/problem.php?id=3707
문제 분류 : 보기
문제 설명 내 문제집에 추가
어떠한 정수 n 이 주어지면, n을 만들수 있는 합의 경우의수를 출력한다. ( 자기 자신 하나의 합은 제외 한다.)
입력
정수 n을 입력받는다. ( 2 <= n <= 60)
출력
경우의 수를 첫줄에 출력한다. 수는 같은데 더하는 순서가 다르면 다른 경우로 판단한다.
입력 예시 예시 복사
7
출력 예시
63
애초에 문제 해결 방법을 떠올리는데 어려웠다.
하지만 여차여차 확인
이 사이트 도움 됨
위의 문제는 같은 공을 서로 다른 상자에 넣는 방식으로 생각하면 좋다. 즉 kHn-k
k개의 상자에 n개의 같은 공 넣기
예를 들어 4개라면 4개의 작대기를 2칸, 3칸 4칸의 다른 상자에 넣는 것으로
2H4-2 + 3H4-3 + 4H4-4 를 구하면 되는 것
이것이 sum에 더해진다.
void recv(int n)
{
unsigned long sum;
sum = 0; // 안해서 에러 1
for (int i = 2; i <= n; i++) // 2 3 4
{
sum += nHr(i, n - i);
//cout << nHr(i, n - i) << " ";
}
cout << sum;
}
그래서 위의 식이 나온다.
nHr nCr 함수는 그냥 그 조합 공식 이용해서 품 대신 memorization기법으로 이미 구했던건 저장
memohh는 필요없을지도?
#include <iostream>
using namespace std;
int memocc[61][61];
int memohh[61][61];
int nCr(int n, int k)
{
if (memocc[n][k])
return (memocc[n][k]);
if (n == 0 || n == 1)
return (1);
if (k == 0 || k == n)
return (1);
memocc[n][k] = nCr(n-1, k-1) % 10007 + nCr(n-1, k) % 10007;
//cout << ans << "\n";
return (memocc[n][k]);
}
int nHr(int n, int r)
{
if (memohh[n][r])
return (memohh[n][r]);
memohh[n][r] = nCr(n + r - 1, r) % 10007;
return (memohh[n][r]);
}
void recv(int n)
{
int sum;
for (int i = 2; i <= n; i++) // 2 3 4
{
sum += nHr(i, n - i);
//cout << nHr(i, n - i) << " ";
}
cout << sum;
}
int main(void)
{
int n;
cin >> n;
//cout << "b" << nCr(3,2);
recv(n);
//cout << memohh[2][2];
}
그래서 이게 나왔는데 틀림 처음에 sum 이 421385? 이렇게 큰 수 나오길래
%10007 해봤는데 아님 알고보니 sum = 0 초기화 안해줘서 ㅋㅋㅋㅋ
#include <iostream>
using namespace std;
int memocc[61][61];
int memohh[61][61];
int nCr(int n, int k)
{
if (memocc[n][k])
return (memocc[n][k]);
if (n == 0 || n == 1)
return (1);
if (k == 0 || k == n)
return (1);
memocc[n][k] = nCr(n-1, k-1) % 10007 + nCr(n-1, k) % 10007;
//cout << ans << "\n";
return (memocc[n][k]);
}
int nHr(int n, int r)
{
if (memohh[n][r])
return (memohh[n][r]);
memohh[n][r] = nCr(n + r - 1, r) % 10007;
return (memohh[n][r]);
}
void recv(int n)
{
int sum;
sum = 0;
for (int i = 2; i <= n; i++) // 2 3 4
{
sum += nHr(i, n - i);
//cout << nHr(i, n - i) << " ";
}
cout << sum;
}
int main(void)
{
int n;
cin >> n;
//cout << "b" << nCr(3,2);
recv(n);
//cout << memohh[2][2];
}
그다음에는 54를 집어넣었을 떄 -1로 오버플로 나서
unsigned long으로 죄다 바꿔줌
#include <iostream>
using namespace std;
unsigned long memocc[61][61];
unsigned long memohh[61][61];
unsigned long nCr(int n, int k)
{
if (memocc[n][k])
return (memocc[n][k]);
if (n == 0 || n == 1)
return (1);
if (k == 0 || k == n)
return (1);
memocc[n][k] = nCr(n-1, k-1)+ nCr(n-1, k);
//cout << ans << "\n";
return (memocc[n][k]);
}
unsigned long nHr(int n, int r)
{
if (memohh[n][r])
return (memohh[n][r]);
memohh[n][r] = nCr(n + r - 1, r);
return (memohh[n][r]);
}
void recv(int n)
{
unsigned long sum;
sum = 0; // 안해서 에러 1
for (int i = 2; i <= n; i++) // 2 3 4
{
sum += nHr(i, n - i);
//cout << nHr(i, n - i) << " ";
}
cout << sum;
}
int main(void)
{
int n;
cin >> n;
//cout << "b" << nCr(3,2);
recv(n);
//cout << memohh[2][2];
}
➜ g++ 3707nsum.cpp;./a.out
54
-1%
이처럼 처음에 오버플로 났다가
➜ g++ 3707nsum.cpp;./a.out
54
9007199254740991%
성공적으로 나온다. :D
성공!
'C언어 > 문제풀다 하나씩' 카테고리의 다른 글
백준 2156 포도주 시식 : nzec 에러만 두번 ㅋㅋ (0) | 2021.02.08 |
---|---|
코드업 4046 학급편성 medium 누적해서 메모리저장 (1) | 2021.02.06 |
백준 11048 이동하기 문제 : 세방향 이동 하지만 두방향만 체크 (0) | 2021.01.29 |
백준 15666 n과 m (12) 헷갈렸다.. prev != arr[i] (0) | 2021.01.25 |
다이나믹 프로그래밍 문제 백준 2579 계단 오르기 문제 d[i][1] d[i][2] (0) | 2021.01.21 |
백준 2309번 일곱난쟁이 || 코드업 codeup 3008 일곱 난쟁이 (0) | 2021.01.20 |
Nqueen문제 (백준 9663 N-Queen & 코드업 3520 체커도전 문제) (0) | 2021.01.19 |
Codeup 코드업 2641 숏다리의 계단 오르기 small (0) | 2021.01.18 |