F - Non-Increasing Number Editorial by en_translator
Define \(\text{d}[x][c]\) as the minimum number of digits of an integer that is congruent to \(x\) modulo \(X\), and a digit greater than or equal to \(c\) can be appended. This dynamic programming (DP) table can be filled in \(O(N\sigma^2)\) time, where \(\sigma=10\), by a Breadth-First Search (BFS) with the transitions \(\text{d}[(10x+c') \bmod N][c'] \leftarrow \text{d}[x][c]+1\) for \(c'=c,c+1,\ldots,9\). (By inspecting in ascending order of \(c'\) and break-ing once reaching an already-searched DP table, it can be easily improved to \(O(N\sigma)\) time.
Consider reconstructing the answer from this DP table. In addition to this table, maintain another two-dimensional array to store, for each element in the DP table, the origin of the transition into that element. Moreover, by performing BFS in ascending order of digits, the minimum value can be obtained by backtracking once you reach a DP-table element with \(x=0\). For more details, please refer to the sample code. (In this code, the two-dimensional array \(\text{d}[x][c]\) is represented as a one-dimensional array \(\text{d}[10\times x+c]\) for speedup.)
from collections import deque
n = int(input())
INF = 10**9
d = [INF] * (10 * n)
to = [-1] * (10 * n)
d[0] = 0
q = deque([0])
while q:
idx = q.popleft()
c, x = idx % 10, idx // 10
for cc in range(max(1, c), 10):
xx = (10 * x + cc) % n
idx2 = 10 * xx + cc
if d[idx2] != INF:
break
d[idx2] = d[idx] + 1
q.append(idx2)
to[idx2] = idx
if xx == 0:
ans = []
cur = idx2
while cur != 0:
ans.append(str(cur % 10))
cur = to[cur]
print("".join(ans[::-1]))
exit()
print(-1)
In fact, the implementation above uses the values stored in \(\text{d}\) only to check if it equals \(\text{INF}\), which happens if and only if \(\text{to}\) contains \(-1\). Thus, the problem can be solved by not explicitly constructing \(\text{d}\) and just maintaining \(\text{to}\).
from collections import deque
n = int(input())
INF = 10**9
to = [-1] * (10 * n)
q = deque([0])
while q:
idx = q.popleft()
c, x = idx % 10, idx // 10
for cc in range(max(1, c), 10):
xx = (10 * x + cc) % n
idx2 = 10 * xx + cc
if to[idx2] != -1:
break
q.append(idx2)
to[idx2] = idx
if xx == 0:
ans = []
cur = idx2
while cur != 0:
ans.append(str(cur % 10))
cur = to[cur]
print("".join(ans[::-1]))
exit()
print(-1)
posted:
last update: