문제 링크
- https://icpc.me/24970
사용 알고리즘
- DP
풀이
수를 반으로 잘라서 앞부분과 뒷부분의 합이 같도록 만들어야 합니다. 즉, (앞부분 절반의 합을 $S$로 만드는 경우의 수)와 (뒷부분 절반의 합을 $S$로 만드는 경우의 수), 그리고 이 조건을 만족하는 수들의 합을 알고 있다면 이들을 활용해 정답을 계산할 수 있습니다.
$C(len, sum, start)$와 $S(len, sum, start)$를 각각 숫자 $len$개를 사용했을 때 합이 $sum$이고, 제일 처음에 사용한 숫자가 $start$인 경우의 수와 그러한 수들의 합으로 정의합시다. 앞부분 절반은 0으로 시작하면 안 되기 때문에 이를 판별하기 위해 $start$가 필요합니다. $a\cdots b$꼴의 수 맨 뒤에 $c$를 추가해서 $a\cdots bc$를 만드는 방식으로 상태 전이를 하면 $C$배열과 $S$배열을 모두 계산할 수 있습니다.
- $C(0,0,0,0) = 1, S(0,0,0,0) = 0$
- $0\leq i < 10$인 $i$에 대해, $C(1,i,i,i) = 1, S(1,i,i,i) = i$
- $C(len,sum,a) \leftarrow C(len-1, sum-c, a)$
- $S(len,sum,a) \leftarrow S(len-1,sum-c,a)\cdot 10 + C(len-1,sum-c,a)\cdot c$
이제 실제로 정답을 구해봅시다. $f(n)$을 길이가 $n$인 균형 수들의 합이라고 정의하면, $\sum_{i=1}^{N} f(i)$를 계산하면 됩니다.
$n$이 짝수라면 앞 $n/2$개의 숫자와 뒤 $n/2$개의 숫자의 합이 동일해야 합니다. 모든 $s$에 대해 아래 식을 더하면 됩니다.
- $\sum_{i=1}^{9} S(n/2,s,i) \cdot \sum_{i=0}^{9} C(n/2,s,i) \cdot 10^{n/2}$
- leading zero 없이 합이 $s$인 수들의 합 / 뒷부분으로 가능한 경우의 수 / 뒤에 숫자 $n/2$개 붙음
- $\sum_{i=0}^{9} S(n/2,s,i) \cdot \sum_{i=1}^{9} C(n/2,s,i)$
- 합이 $s$인 수들의 합 / 앞부분으로 가능한 경우의 수
$n$이 홀수라면 앞 $\lfloor n/2\rfloor$개의 숫자와 뒤 $\lfloor n/2\rfloor$개의 숫자의 합이 동일하고, 그 사이의 숫자 하나가 들어가야 합니다. 모든 $0 \leq s < 10\cdot\lfloor n/2\rfloor$에 대해 아래 식을 더하면 됩니다.
- $\sum_{i=1}^{9} S(n/2,s,i) \cdot \sum_{i=0}^{9} C(n/2,s,i) \cdot 10 \cdot 10^{n/2+1}$
- leading zero 없이 합이 $s$인 수들의 합 / 뒷부분으로 가능한 경우의 수 / 가운데 들어갈 수 있는 숫자 개수 / 뒤에 숫자 $\lfloor n/2\rfloor + 1$개 붙음
- $\sum_{i=1}^{9} C(n/2,s,i) \cdot \sum_{i=0}^{9} C(n/2,s,i) \cdot 45 \cdot 10^{n/2}$
- 앞부분으로 가능한 경우의 수 / 뒷부분으로 가능한 경우의 수 / 가운데 들어갈 수 있는 수들의 합 / 뒤에 숫자 $\lfloor n/2\rfloor$개 붙음
- $\sum_{i=0}^{9} S(n/2,s,i) \cdot \sum_{i=1}^{9} C(n/2,s,i) \cdot 10$
- 합이 $s$인 수들의 합 / 앞부분으로 가능한 경우의 수 / 가운데 들어갈 수 있는 숫자 개수
$C(len,sum,\ast)$의 합과 $S(len,sum,\ast)$의 합도 같이 전처리하면 빠르게 정답을 계산할 수 있습니다.
전체 코드
1 |
|