pstopia Notes for Problem Solving Contest

[Hard] VerySmoothDecompositions

Topcoder SRM 519 Div1

Problem

16이하의 수들의 곱으로 나타내야 하므로 주어진 수 N은 N = 2^p2 * 3^p3 * 5^p5 * 7^p7 * 11^p11 * 13^p13 으로 나타낼 수 있어야 한다. 2, 3, 5, 7, 11, 13 으로 계속 나눠서 p2, p3, p5, p7, p11, p13 의 값을 구하고 다 나눈 뒤에도 1보다 큰 수가 남는다면 16이하의 수들의 곱으로는 나타낼 수 없다는 뜻이므로 답은 0이 된다. decomposition 에 나타나는 2의 개수를 a2, 3의 개수를 a3, 4의 개수를 a4, ... 라고 정의하면 p2 = a2 + 2*a4 + a6 + 3*a8 + a10 + 2*a12 + a14 + 4*a16 p3 = a3 + a6 + 2*a9 + a12 + a15 p5 = a5 + a10 + a15 p7 = a7 + a14 p11 = a11 p13 = a13 이 성립한다. 위의 식을 만족하는 {a2, a3, a4, ..., a16} 의 경우의 수를 구하는 문제로 바뀐다. 상태 공간의 일부를 brute force 로 결정하고 나머지를 잘 찾는 식으로 모든 경우의 수를 셀 수 있다. 여러가지 방법이 있을텐데 에디토리얼에 나와있는 방법을 설명하겠다. a11과 a13은 바로 결정이 되므로 관심에서 제외해도 된다. a15, a14, a10 을 각각 결정했다고 해보자. 우선, 식에 의해 a5, a7 의 값이 결정되고, 나머지 식을 정리하면 아래와 같다. p2 - a10 - a14 = a2 + 2*a4 + a6 + 3*a8 + 2*a12 + 4*a16 = x p3 - a15 = a3 + a6 + 2*a9 + a12 = y 남은 변수들로 2^x * 3^y 꼴의 수가 만들어진다. x*y 의 범위가 생각보다 작으므로 다음과 같은 DP를 생각할 수 있다. z = { 2, 3, 4, 6, 8, 9, 12, 16 } D[i][x][y] = z[1] ~ z[i] 의 수를 이용해 2^x * 3^y 꼴의 수를 만드는 경우의 수 = D[i-1][x][y] + D[i][x - (z[i]에 있는 2의 개수)][y - (z[i]에 있는 3의 개수)] 이 DP를 미리 계산해놓으면 a15, a14, a10 을 결정한 후, D[8][p2-a10-a14][p3-a15] 의 값을 답에 더하는 식으로 전체 경우의 수를 계산할 수 있다. x*y 의 범위를 구체적으로 생각해보자. x, y 는 2^x * 3^y <= D < 10^2500 x*log10(2) + y*log10(3) < 2500 를 만족한다. 이 때, x*y 가 최대가 되는 곳은 대략 x=4152, y=2620 쯤 이므로 위의 DP는 시간, 공간 제약 내에서 계산할 수 있다. a15, a14, a10 의 가능한 경우를 모두 다 살피기엔 그 경우의 수가 너무 많으므로 한가지 최적화가 더 필요하다. a15 를 먼저 결정하면 p3-a15 의 값이 결정된다. 따라서 D[8][i][p3-a15] 의 prefix sum 을 구해놓으면 이를 이용해 a10을 직접 결정하지 않고도 답을 계산할 수 있다.