pstopia Notes for Problem Solving Contest

[Hard] ProductAndSum

Topcoder SRM 500 Div1

Problem

조건을 만족하는 수 N의 digit 중 1의 개수를 d[1], 2의 개수를 d[2], ..., d[9] 라고 하자. (N의 digit에는 0이 있을 수 없으므로 d[0]은 의미없음) 전탐색을 하는데 신묘한 방식으로 경우의 수를 쳐낼 것이다. 일단 자명하게 d[5] = p5, d[7] = p7 이다. 먼저 d[6]을 고정한다. 그럼 d[8] <= (p2 - d[6]) / 3 , d[4] <= (p2 - d[6] - 3 * d[8]) / 2 , d[9] <= (p3 - d[6]) / 2 이다. 위의 범위 안에서 d[8], d[4], d[9]를 고정한다. 그럼 나머지가 다음과 같이 결정된다. d[2] = p2 - d[6] - 2 * d[4] - 3 * d[8] d[3] = p3 - d[6] - 2 * d[9] d[1] = S - (2 * d[2] + 3 * d[3] + 4 * d[4] + 5 * d[5] + 6 * d[6] + 7 * d[7] + 8 * d[8] + 9 * d[9]) (물론 d[1], d[2], d[3] >= 0 이어야 함) 이런 식으로 d[6], d[8], d[4], d[9] 를 잡는 경우의 수는 대략 8백만개 정도 된다. 다 돌려보면서 확인할 수 있다. 이제 d 수열을 결정했을 때 답을 O(1)에 구할 수 있으면 된다. 수의 길이 L = sum(d[i]) , 수의 가짓수 K = L! / (d[1]! * d[2]! * d[3]! * ... * d[9]!) 각 자리에 i가 등장하는 횟수는 K * (d[i] / L) 이므로 ( sum( i * d[i] ) * K / L ) * m 만큼 답에 더해주면 된다. ( m은 L자리의 1로 이루어진 수 ) 이를 O(1) 에 처리하기 위해서 팩토리얼, 역수 등을 전처리로 미리 구해놓자