Предположим, номер, который вы начали, выглядит как xyz
. То есть его последняя (десятичная) цифра равна z, ее предпоследней цифрой является y, а остальное x. В вашем примере, если вы начали с 504, тогда x = 5, y = 0, z = 4. Значение вашего исходного номера равно 100x + 10y + z.
Число, в котором вы закончите, представляет собой сумму (100x + 10y + z), (10x + y) и x. Это 111x + 11y + z.
Обратите внимание, что наши ограничения заключались в том, что 0≤y≤9 и 0≤z≤9. Даже с их наибольшими значениями мы имеем 11y + z ≤ 11 (9) + 9 < 111. Таким образом, мы можем инвертировать преобразование: вытащить наибольшее кратное 111, затем вытащить наибольшее кратное 11 из оставшихся, а затем то, что осталось.
def transform(n):
return n + (n/10) + (n/100)
def invert(m):
[x, y, z] = [m/111, (m%111)/11, (m%111)%11]
return 100*x + 10*y + z
assert transform(504) == 559
assert invert(559) == 504
(Попробуйте выше, в оболочке Python Обратите внимание, что это работает, даже если й не одноразрядный номер:.. transform(12345)
дает 13702, и invert(13702)
дает 12345, как и ожидался)
Редактировать: Альтернативное решение, основанное на идее в Paul Hankin's answer (пожалуйста, подтвердите это) с использованием m*100/111
в качестве отправной точки. Вы можете использовать (потолок) это значение как грубый ответ и попробуйте добавить 1 и 2, чтобы получить точный ответ, но вы также можете прекомпотировать «смещение», необходимое из грубого ответа.
# Precomputation, to populate the "offset" dictionary
def sane_mod(a, m): return ((a % m) + m) % m
offset = {}
for y in range(10):
for z in range(10):
add = 10*y + 11*z
offset[sane_mod(-add, 111)] = add
# Actual function
def invert2(m):
rough = m * 100
return (rough + offset[rough % 111])/111
assert invert2(559) == 504
Если a + b + c мало (<= 10^6), мы можем использовать bruteforce, попробуйте каждую возможность от 1 до a + b + c. – algojava