백준 1086 - 박성원 (Python)

Updated:

개인적으로 너무 어려웠던 문제입니다.
다른 분들의 풀이를 많이 참고했습니다.

핵심 코드

tmp = 0
    for i in range(n):
        if not bit & (1 << i):
            new_mod = ((mod * mod_10[a_len[i]]) % k + a[i]) % k
            tmp += dfs(new_mod, bit | (1 << i))

    dp[mod][bit] = tmp

4번째 줄의 의미는 나머지 연산의 특성을 생각하면 알 수 있습니다.
dp[나머지][비트]에는 비트 % k == 나머지 일 때 가능한 비트들의 수를 저장한다.

나머지 연산 특성

(a + b) % c == (a % c + b % c) % c
(a - b) % c == (a % c - b % c) % c
(a * b) % c == (a % c * b % c) % c

나눗셈일 때는 성립하지 않아서 곱셈의 역원으로 계산해야 합니다.

나머지 부분은 주석으로 설명하겠습니다.

import sys
from math import factorial, gcd

input = sys.stdin.readline

def solution(mod, bit):
    if bit == (1 << n) - 1: # 끝까지 다 돌았을 때
        if mod == 0: # 나누어 떨어질 때
            return 1
        return 0

    if dp[mod][bit] != -1: # 이미 저장된 값이 있을 때
        return dp[mod][bit]

    tmp = 0
    for i in range(n):
        if not bit & (1 << i):
            # 나머지가 i 인 모든 비트들을 찾아서 더해줌
            new_mod = ((mod * mod_10[a_len[i]]) % k + a[i]) % k
            tmp += dfs(new_mod, bit | (1 << i))

    dp[mod][bit] = tmp
    
    return dp[mod][bit]

n = int(input())
a = [int(input()) for _ in range(n)]
k = int(input())

dp = [[-1] * (1 << n) for _ in range(k)]
a_len = [len(str(i)) for i in a] # 나머지 계산을 하기 위해 미리 계산
a = [i % k for i in a]

mod_10 = [1]
for i in range(50): # 나머지 계산을 하기 위해 미리 계산
    mod_10.append((mod_10[-1] * 10) % k)
    
answer = solution(0, 0)

if answer == 0:
    print('0/1')
else:
    f = factorial(n)
    if answer == f or k == 1:
        print('1/1')
    else:
        m = gcd(answer, f)
        print('{}/{}'.format(answer // m, f // m))

Categories:

Updated: