85 шагов для "калькулятора" (x→x+1, x→2x, x→3x)
Имеется калькулятор с тремя операциями.
Дано натуральное n. Сколько операций x→x+1, x→2x, x→3x нужно, чтобы из единицы построить n?
Задача: отыщите n: 1 ≤ n < 264 для получения которого необходимо 85 операций.
Пояснения
Исходная задача: Не получается решить задачу на программирование: калькулятор.
Последовательность A056796 на единицу больше количества операций этого калькулятора.
Ограничение n < 264 важно. Не так сложно взять большое n и получить большой ответ (n = 1068 требует 224 операции). Требуется найти не очень большое n с большим ответом.
84 операции для 18 446 744 025 449 496 575.
Новости
Ответ gord1402: 94 шага для 232320 - 1 (= 14 975 624 970 497 949 695). Это значительно лучше чем запрошенные 85. Это даже значительно больше чем моя оценка верхнего порога – 90.
95? Или 94 но для меньшего n?
Ответы (2 шт):
Понятно что число с максимальным количеством операций будет максимально удалено от степеней 3-х и 2-х. В таком случае нам нужно лишь просмотреть числа 2**a * 3**b - 1, что сокращает количество чисел до ~64 * 40. Вот решение, что я написал:
import collections
import tqdm
def problem85(n):
graph = {}
queue = collections.deque()
queue.append((n, 0))
while queue:
a, b = queue.popleft()
if a not in graph:
graph[a] = b
if a == 1:
break
q, r = divmod(a, 3)
if r == 0:
queue.append((q, a))
q, r = divmod(a, 2)
if r == 0:
queue.append((q, a))
queue.append((a - 1, a))
m = 1
path = [m]
while m != n:
m = graph[m]
path.append(m)
return len(path) - 1
results = []
for pow2 in tqdm.tqdm(range(64)):
for pow3 in range(40):
if ((pow2 == 0 and pow3 == 0) or (2 ** pow2 * 3 ** pow3) > 2 ** 64): break
result = problem85(2**pow2 * 3 ** pow3 - 1)
if result > 60:
results.append([result, pow2, pow3])
for result in sorted(results, key = lambda x:x[0]):
print(result)
Где problem85 - функция решения оригинальной задачи.
Вот топ лист:
[87, 40, 15]
[88, 28, 21]
[88, 29, 20]
[88, 31, 18]
[88, 36, 17]
[89, 27, 23]
[89, 28, 22]
[89, 30, 19]
[89, 32, 18]
[89, 35, 17]
[89, 37, 17]
[90, 29, 21]
[90, 30, 20]
[90, 33, 18]
[90, 34, 18]
[91, 29, 22]
[91, 31, 19]
[92, 30, 21]
[92, 31, 20]
[92, 32, 19]
[92, 35, 18]
[93, 33, 19]
[94, 32, 20]
Я воспользовался великолепной идеей из ответа gord1402. У меня уже была таблица рекордов (она есть на OEIS: https://oeis.org/A056817), полученная полным перебором. Для каждого числа операций я отыскал минимальное n требующее это количество операций. Например 143 строится за 10 операций, а все числа меньше требуют меньше операций.
Я попробовал к рекордам добавлять небольшие числа так, чтобы сумма делилась на много двоек и троек: 143 + 1 = 24·32.
Иногда деление не полное, остаётся небольшой множитель. Рекорд для 20 разлагается так:
12959 + 1 = 25·34·5.
Получилась таблица ниже. Она составлена неформально: сперва подбиралось небольшое t, потом проверялось что сумма "хорошо" разлагается. Но это всегда срабатывало: t принимает значения 0, 1, 2 и 5, а оставшийся после исключения двоек и троек множитель f – 1, 5 и 7.
| fn | n = 2a·3b·f - t | fn | n = 2a·3b·f - t |
|---|---|---|---|
| 0 | 1 = 1 | 32 | 2799359 = 28·37·5 - 1 |
| 1 | 2 = 2 | 33 | 4478975 = 211·37 - 1 |
| 2 | 4 = 22 | 34 | 5598719 = 29·37·5 - 1 |
| 3 | 5 = 2·3 - 1 | 35 | 16796159 = 29·38·5 - 1 |
| 4 | 11 = 22·3 - 1 | 36 | 23514623 = 29·38·7 - 1 |
| 5 | 17 = 2·32 - 1 | 37 | 33592319 = 210·38·5 - 1 |
| 6 | 23 = 23·3 - 1 | 38 | 53747711 = 213·38 - 1 |
| 7 | 35 = 22·32 - 1 | 39 | 94058495 = 211·38·7 - 1 |
| 8 | 70 = 23·32 - 2 | 40 | 141087743 = 210·39·7 - 1 |
| 9 | 71 = 23·32 - 1 | 41 | 214990847 = 215·38 - 1 |
| 10 | 143 = 24·32 - 1 | 42 | 282175487 = 211·39·7 - 1 |
| 11 | 215 = 23·33 - 1 | 43 | 564350975 = 212·39·7 - 1 |
| 12 | 430 = 24·33 - 2 | 44 | 644972543 = 215·39 - 1 |
| 13 | 431 = 24·33 - 1 | 45 | 1128701951 = 213·39·7 - 1 |
| 14 | 863 = 25·33 - 1 | 46 | 1693052927 = 212·310·7 - 1 |
| 15 | 2158 = 24·33·5 - 2 | 47 | 2579890175 = 217·39 - 1 |
| 16 | 2159 = 24·33·5 - 1 | 48 | 3386105855 = 213·310·7 - 1 |
| 17 | 4319 = 25·33·5 - 1 | 49 | 6772211711 = 214·310·7 - 1 |
| 18 | 6479 = 24·34·5 - 1 | 50 | 10158317567 = 213·311·7 - 1 |
| 19 | 8639 = 26·33·5 - 1 | 51 | 13544423423 = 215·310·7 - 1 |
| 20 | 12959 = 25·34·5 - 1 | 52 | 20316635135 = 214·311·7 - 1 |
| 21 | 25918 = 26·34·5 - 2 | 53 | 40633270270 = 215·311·7 - 2 |
| 22 | 25919 = 26·34·5 - 1 | 54 | 40633270271 = 215·311·7 - 1 |
| 23 | 51839 = 27·34·5 - 1 | 55 | 81266540543 = 216·311·7 - 1 |
| 24 | 77759 = 26·35·5 - 1 | 56 | 121899810815 = 215·312·7 - 1 |
| 25 | 155518 = 27·35·5 - 2 | 57 | 162533081087 = 217·311·7 - 1 |
| 26 | 155519 = 27·35·5 - 1 | 58 | 243799621631 = 216·312·7 - 1 |
| 27 | 311039 = 28·35·5 - 1 | 59 | 487599243262 = 217·312·7 - 2 |
| 28 | 466559 = 27·36·5 - 1 | 60 | 487599243263 = 217·312·7 - 1 |
| 29 | 933118 = 28·36·5 - 2 | 61 | 1462797729787 = 217·313·7 - 5 |
| 30 | 933119 = 28·36·5 - 1 | 62 | 1462797729791 = 217·313·7 - 1 |
| 31 | 1866239 = 29·36·5 - 1 | 63 | 6269133127679 = 218·314·5 - 1 |
Дальше я повторил поиск gord1402 меняя параметры a, b, f, t. f менялся в диапазоне [1, 30] (брались только значения взаимно простые с 2 и 3), t – в диапазоне [0, 20]. Для 2a·3b·f - t рассчитывалось количество операций. Рекорды для 85, 94, 95:
85: n = 136496581762351103 = 224·319·7 - 1
94: n = 9827753886889279487 = 227·321·7 - 1
95: n = 13103671849185705983 = 229·320·7 - 1
Доказательства у меня нет, но я думаю что все рекорды имеют структуру замеченную gord1402. Если так, то 95 – самое большое число операций для n < 264.