티스토리 뷰

https://www.acmicpc.net/problem/11051



이 문제를 풀기 위해서는 먼저 이항계수에 대해 알아야 합니다.


11050번 문제와는 달리 메모이제이션이라는 방법을 이용하여 풀어보겠습니다.


메모이제이션이라는 방법은 간단히 설명하면 메모를 해두어 메모가 되어있는 정보들은 바로 이용하는 방법입니다.


더 자세히 아시고 싶은 분은 나무위키를 참조하시기 바랍니다. 

(https://ko.wikipedia.org/wiki/%EB%A9%94%EB%AA%A8%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98)


먼저 이항계수를 구하는 방법을 11050번 문제와 다른 공식을 이용하겠습니다.


$$n\mathbf{C}r = n-1\mathbf{C}r-1 + n-1\mathbf{C}r$$


위 공식을 이용할텐데 조금 더 자세하게 설명해보도록 하겠습니다.





파스칼의 삼각형을 보면 이해하기 쉽습니다.


위 삼각형에서 예시를 들어보겠습니다.


$$4\mathbf{C}2 = 3\mathbf{C}1 + 3\mathbf{C}2$$


원하는 값의 좌우측 상단을 더하면 된다는 것을 알 수 있습니다.


이것을 이용하여 파이썬 코드로 구현해보겠습니다.



fact = [[0 for i in range(1001)] for j in range(1001)]
fact[0][0] = fact[1][0] = fact[1][1] = 1
for i in range(2, 1001):
    for j in range(0, i+1):
        if i == j or j == 0:
            fact[i][j] = 1
        elif fact[i][j] == 0:
            fact[i][j] = fact[i-1][j-1] + fact[i-1][j]


fact라는 리스트에 이항계수 값들을 저장하겠습니다.


1001 X 1001 리스트를 0으로 초기화했습니다.


그 후 fact[0][0] fact[1][0] fact[1][1] 을 1으로 변경했습니다. 이 값들을 이용하여 재귀법으로 모든 값들을 구할 수 있습니다.


구해진 값들을 fact리스트에 저장을 하면 이후에 구하는 값들은 재귀하는 횟수가 줄어듭니다.


다만 이 방법은 메모리를 굉장히 많이 요구하는 방법입니다.



N, K = map(int, input().split())
print(fact[N][K] % 10007)


출력은 간단하게 fact리스트에 저장된 값들을 불러와 나머지를 구하는 것으로 마무리하면 되겠습니다.




fact = [[0 for i in range(1001)] for j in range(1001)]
fact[0][0] = fact[1][0] = fact[1][1] = 1
for i in range(2, 1001):
    for j in range(0, i+1):
        if i == j or j == 0:
            fact[i][j] = 1
        elif fact[i][j] == 0:
            fact[i][j] = fact[i-1][j-1] + fact[i-1][j]

N, K = map(int, input().split())
print(fact[N][K] % 10007)