Теорию читал, но практически с алгоритмом не пойму вторые сутки. А именно:
1 этап. Табличка со степенями числа в двухмерном массиве в зависимости от длинны числа создана и работает. DONE
2 этап. Реализовать алгоритм проверки чисел на уникальность (135, 153, 531 и т.п.) удалось. Даже проблему отсутствующего нуля, когда 37 не равно 370, тоже вроде как понятно, как решать. почти DONE
3 этап. Вопрос - где и как вы храните сумму степеней чисел, описанных в пункте 2? Я использовал HashMap cо стринговым ключем (например, ключ (проверяемое уникальное число) - значение (сумма степеней его чисел). Но при извлечении из МАП, если число не уникально (т.е. уже точно там есть), без проверки map.contains() невозможно. В целом, это все равно долго. Тут и проблема.
4 этап. Проверка уникального рассчитанного числа или извлеченного на Армстронговость и запись в массив. DONE
Andrey Karelin
41 уровень
Помогите с алгоритмом!
Обсуждается
Комментарии (17)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
oOWOo
13 августа 2020, 21:45
Длину чисел!
патом проста в цикле можеш в степень
где интермедиеит твои номер так ты с конца берёш остаток! и Math.pow(остаток, length)
плюсуеш к суме есле сума ровна и номером суёш в Array патом делоеш из result
0
Andrey Karelin
12 августа 2020, 13:48
Вот, например, как по числу 110 мы видим, что его уже проверяли, если карты (списка) проверенных чиселу нас нет?
Мы видим, что 0 меньше 1 по порядку, значит делаем вывод, что проверяли.
Так и есть. Значит установка, что каждая след.цифра в числе не меньше предыдущей, вроде как правильная.
Но
по числу 370 мы делаем такой же вывод, глядя на 0 после 7. И в числе 307 (потому что 0 после 3.
А на самом деле то мы его не проверяли.
Как мы должны понять, что число 307 мы все же должны отправить на проверку, а 370 не отправлять?
Другими словами, получая на вход 300, по логике мы генерируем 333 на проверку. Почему мы должны сгенерировать 307?
0
Евгений
30 июля 2020, 20:03
А зачем их где то хранить? Если делать генератор из статьи, то каждый набор чисел будет только один раз, поэтому сразу сумму степеней посчитать и тут же проверить.
0
JustinianJudge в Mega City OneMaster
30 июля 2020, 12:21
Я делал как написано в статье:
https://acmp.ru/article.asp?id_text=198
0
Andrey Karelin
30 июля 2020, 19:43
статья уже давно зачитана/перечитана до дыр.
там говорится, что например из группы чисел 135, 153, 531, 315 и т.д. сумма степеней считается только один раз. Это значит, что посчитана первый раз она должна где хранится? в листе?? чтобы вытащить ее еще раз и сравнить с числом.
Потом еще... "проверять нужно числа, каждая следующая цифра которого не меньше предыдущей". Как так, то, если 370 и 371 - это числа Армстронга, но на проверку они бы не отпоавились, т.к. 0 и 1 меньше 7. Чето путаница какая-то совсем.
0
JustinianJudge в Mega City OneMaster
30 июля 2020, 20:13
Невнимательно значит прочитана
обычный двумерный массив
Насчет нулей, да, нужно подумать,
370 будет проверяться на 307
а 371 будет проверяться на 137
Попробуй найти закономерность что делать с нулями, и отобразить это в коде.
0
Andrey Karelin
30 июля 2020, 20:36
так, если мы отбросим числа с повторяющимся набором цифр ( 135, 531, 315 и т.п.), и расчитаем для числа степенную сумму(чтобы в массив поместить), так останется только сравнить ее с числом на армстронговость оператором ==, и если равно, то сразу занести в аррейлист армстронга.
Зачем ее в таблицу заносить, чтобы потом вторым перебором доставать снова и сравнивать сумму степеней с числом?
0
Andrey Karelin
30 июля 2020, 20:50
То есть в двухмерном массиве в столбце "i" будут все числа от 0 до N (за исключением повторяющихся наборов цифр в комбинации числа) , а в "j" столбце сумма степеней числа "i" до количества цифр в проверяемом числе. так?
т.е. мы будем по формуле каждый раз просчитывать сумму степеней класть в ячейку массива, а потом снова с нуля доставать и проверять?
0
JustinianJudge в Mega City OneMaster
30 июля 2020, 22:00
есть разные реализации алгоритма.
Я делал табличку от 0 до 9 по одной оси, и от 0 до 19 по другой
То есть возможных цифр всего 10 вариантов (от 0 к 9), и этих цифр в числе может быть не больше 19 (максимальная разрядность лонга), соответственно
153 это я обращался к трем элементам массива, [1][3], [5][3], [3][3], то есть разряд конкретный и степень.
Но повторюсь, вариантов много.
Сами перебираемые числа, при простом переборе не помещаются, как решают мультимножествами - не разбирал, там другой алгоритм
0
Andrey Karelin
30 июля 2020, 22:46
построение такой таблицы в виде двухмерного массива, где цифры от 0 до 9 возводятся в степень числа-количества цифр от N - это самая понятная часть "ускорения" расчетов.
Она позволяет не расчитывать сотый раз степени чисел от 0 до 9, а брать их из таблицы.
Остается понять, как по максимуму отсеять перебор чисел от 0 до N в цикле складывания таких степеней и сравнения с выбранным числом в цикле.
0
JustinianJudge в Mega City OneMaster
31 июля 2020, 10:07
Как отсеять в статье написано, нужно не перебирать, а генерировать следующее число по определенному паттерну
Чтобы после 20 шло 22, поскольку 21 проверялось на 12
после 80 шло 88, поскольку 81 проверялось на 18, 82 на 28 и тд.
+ обработать нули.
логично что 370 на 037 не проверишь. А где мы можем это проверить? на 307.
Если ты поймешь закономерность, то сможешь реализовать это в коде
+1
Andrey Karelin
4 августа 2020, 13:18
Из пояснений в тиражируемой статье понятно, что если мы считали сумму степеней числа 135, то считать сумму степеней числа 351, 531, 153.. не нужно. Но логика не раскрывается далее, потому что посчитав 135, а затем мы доходим до числа 153 и видим, что сумма уже есть. Но все равно перебор идет всех чисел, только сумма не считается.
А каким "макаром" перелетать через десятки/сотни? (то есть в переборе(цикле) сделать i+z, но не "перелететь" очередное проверяемое число, я так и не понял.
Опять же 370, 371 - это неправильные цифры (по логике статьи), хотя они должны быть в итоговом массиве long.
Короче, решение я нашел, чужое. Я даже ускорил его в два с лишним раза. Но даже разбирая сутки! логику прироста "i" при переборе, я так и не постиг. Чисто с математической точки зрения.
0
JustinianJudge в Mega City OneMaster
4 августа 2020, 13:46
Зря нашел чужое решение, значит эту задачу ты не решил, а она очень прикольная и полезная. Но такое.
Во-первых, постановка проблемы.
вот этот код, пустой цикл, в котором нет ничего, по расчетам на стекофервлоу будет исполняться около..230-250 лет.
Из этого следует вывод - что прямой перебор это не вариант.
Поэтому через числа прыгают.
Дошел до 80, прыгнул на 88, поскольку:
81 проверялось на 18
82 проверялось на 28
и тд
то есть мы не итерируемся последовательно, а генерируем следующее число вручную по определенной логике.
В статье это ряд правил, чтобы каждый разряд был не больше предыдущего и тд + отдельно нули.
НА малых числах, казалось бы, с 80 до 88..но на огромных чисел это перескакивание через миллиарды и триллионы чисел.
ИТОГО, как ты понимаешь:
до 153 мы никогда не дойдем, оно уже было проверено на 135 и доходить нам к нему не нужно.
+
матрица степеней, чтобы не считать каждый раз степень для разряда, мы помещаем в матрицу 10 на 19 уже готовые значения, где от 0 до 9 возможнные арабские цифры, которые встретятся в разряде, а 19 это максимальное количество возможной степени (поскольку Long.MAX_VALUE 19 разрядное).
это в принципе решение в лоб, поскольку это простая комбинаторика.
В более упрощенном виде это как задача "напишите часы, чтобы после 23:59 было 00:00", то есть, просто есть дополнительная логика, инкрементируемся +1 если это не такие-то условия, хотя реализовать можно по разному.
Решения не в лоб, это уже всякие алгоритмы, как например решения на мультимножествах, которое считает за 0.4 с, но есть много других вариантов.
+1
Andrey Karelin
12 августа 2020, 12:08
блин, вторая неделя пошла...голова уже дымит (хочу все же написать сам программу), но так и не пойму...
Ну первую десятку загнали сразу (от 1 до 9), далее 11, 12.....33,34 ....133, 134, 135 (проверили, получаем из него Армстронга 153, записали в массив), далее какое смотрим 136? Или переходим сразу на 155( меньше в итоговом списке ведь нет) . Если 155, тогда 137 мы не проверили (а получили бы 371 число армстронга).
...едем, например по списку 298, 299, далее 333 (как программа может понять, что надо проверить 307???). Далее 369, 377 (370, 371 прошляпили)..... если мы берем как "уникальный критерий" рост цифр в номере. То есть первое число в 3й сотне для проверки - это 333, в четвертой - 444. 370, 371, 407и т.д куча цифр из списка вылетает совсем.
Ладно, я допустим жестко задам, чтобы в двухразрядных цифрах вставляля "0" для проверки. ...
Вообщем цифры до четырех разрядов я логически могу задать, как их вытащить "на свет", Но по моему алгоритму не попадают в вывод несколько числе 6 - 7 разрядных, и совсем без нулей. Как там логику понять (с помощью калькулятора и листочка) я уже не могу осилить.
Вот самый основной то момент и не понятен - АЛГОРИТМ. Как понять в динамике какое число за которым брать??? По-момоему - это задача не программисту, а для магистра высшей математики или комбинаторики какой-то.
И главное то - мы имеем цифры ряда, и пытаемся построить алгоритм, который бы быстро выводил их на экран. Но мы то их знаем изначально. А если не знали бы, то построить алгоритм, который бы их правильно и моментально вывел невозможно.
0
JustinianJudge в Mega City OneMaster
12 августа 2020, 12:43
здесь простая комбинаторика, просто нужно поднапрячь внимание.
В чем суть. Тебе нужно исключить те числа, которые уже раньше были проверены.
Чтобы не проверять по миллиарду раз одно и то же (на большеразрядных числах).
Забудь пока про арсмтронга. Считай что твоя задача звучит следующим образом, написать генератор чисел, который задает их таким образом, чтобы не повторялись комбинации разрядов
это ок
это НЕ ок.
поскольку 78 и 87 имеет одинаковый набор разрядов - цифры 7 и 8.
1
..
9
10
..
19
20
исключается 21 (поскольку на 12 проверялось)
22
23
24
25
26
27
28
29
30
33
..
40
44
...
..
88
89
90
99
100
101
102
103
104
105
106
107
108
109
110 (исключается , проверялось на 101)
111
112
...
119
122
это схематично, отдельное внимание обрати на нули, в ряде случаев их нужно оставлять, поскольку
10 мы оставляем, так как
01 не было
111101 мы проверяем так как
011111 мы не пишем.
НО
111101
110111
101111
проверять не нужно поскольку число с единиц и одним нулем было проверено на
111110
То есть сначала, ты просто нарисуй последовательности на бумажке, посмотри какие закономерности чтобы числа не повторялись
, нули отдельный случай не забудь.
А тогда когда ты поймешь для себя какая последовательность есть, тогда можешь и в алгоритм перенести. ИНаче сложно писать алгоритм, если не понимаешь что он должен делать.
Вот я например не совсем понял почему ты предлагаешь после 135 идти к 155. А число 144 к примеру когда было/будет проверено? или 139?
0
Andrey Karelin
12 августа 2020, 13:39
То, что цифры проверять по возрастанию и без повторов, это понятно давно.
Когда мы проверяем, например, число 370? после какого числа? когда 371, после какого?
- 37? Так "0" нет. Можно довставить, например все числа от 10 до 99 проверять как 010...099.
- 307, 370, 730 по логике мы должны пропустить, т.к. 299...затем 333, 334....369, 377 и т.п.
Можно пример, потому что все вокруг да около, сотню раз о том, то и так понятно, но я не могу родить, не представляя.(
0
JustinianJudge в Mega City OneMaster
12 августа 2020, 14:38
ты не ответил на вопрос, как у тебя после 135 идет 155.
Еще раз. Суть в том, что у тебя должна быть определенная последовательность чисел перечитай мой коммент не хочу повторять.
В этой последовательности должны быть комбинации всех возможных разрядов, я привел пример.
307 проверяется на 307. Поскольку оно раньше проверялось? Нет. Значит мы его проверяем, я уже писал - 0 мы обрабатывает отдельно от логики предыдущий разряд не ниже следующего или как там.
010 проверять так не получится, В десятичной системе таких чисел нет
Напиши алгоритм последовательность чисел, от 1 до 1000 к примеру, и давай алгоритм сюда, а то мы воздух тут колотим, нужно отталкиваться от конкретики, реализуй пусть с ошибками или как получается, но чтобы хоть было что-то обсуждать.
0