PS

[Code Jam 2021 Round 2] Matrygons 풀이

yonsweng 2021. 5. 16. 22:26

N개의 side를 채우기 위해 작은 Polygon부터 생각해보면 polygon의 side 개수는 배수로 증가한다.

예를 들어, 33 = 3(1+10) 혹은 11(1+2)와 같이 나타낼 수 있다. 재귀적으로 3(1+10)은 또 3(1+2(1+4))와 같이 나타낼 수 있다.

f(p)를 다음과 같이 정의하자.

f(p) : p를 만들기 위해 2보다 크거나 같은 p의 약수 qi를 사용해서 p=q0+q0q1+q0q1q2+...+q0q1...qn으로 나타낼 때 최대 항의 수

말이 좀 어려운데, 예를 들어보면 22=2(1+10)=2(1+2(1+4))이므로 f(22)=3이다.

g(p) : p를 만들기 위해 3보다 크거나 같은 p의 약수 qi를 사용해서 p=q0+q0q1+q0q1q2+...+q0q1...qn으로 나타낼 때 최대 항의 수

 

 

$$ f(p)=1+max_{{2{\leq}q<p}, {q|p}}f(p/q-1) $$

$$ g(p)=1+max_{{3{\leq}q<p}, {q|p}}f(p/q-1) $$

 

 

g(N)을 구하면 답이 된다. 왜냐하면 최소 polygon의 side 개수는 3이고 3으로 묶은 다음 그 다음부터는 2 이상인 약수로 최대한 많은 항의 수로 묶는 것이 답이 되기 때문이다.

Python 코드는 다음과 같다.

MAX = 1000000

T = int(input())
N = []
for x in range(1, T + 1):
    N.append(int(input()))

divisors = [[] for _ in range(MAX + 1)]
for d in range(2, MAX + 1):
    for n in range(2 * d, MAX + 1, d):
        divisors[n].append(d)

f = [0] * (MAX + 1)
f[2] = 1
g = [0] * (MAX + 1)
for n in range(3, MAX + 1):
    max_f, max_g = 1, 1
    for q in divisors[n]:
        max_f = max(max_f, f[n//q-1]+1)
        if q > 2:
            max_g = max(max_g, f[n//q-1]+1)
    f[n] = max_f
    g[n] = max_g

for x in range(1, T + 1):
    print(f'Case #{x}: {g[N[x-1]]}')