|
|
|
Число, делящееся на n и с суммой цифр n04.12.2013, 15:21. Показов 6641. Ответов 47
Метки нет (Все метки)
Встала задача, которую нужно решить в кратчайшие сроки, но решения я не могу придумать.
Дано число n (от 1 до 1000), необходимо найти такое минимальное m, что m=kn и ds(m)=n, где ds возвращает сумму цифр числа в 10-й системе записи. Работаем в натуральных числах. Ограничения по времени: несколько секунд. Варианты решения. Кликните здесь для просмотра всего текста
Составляем потенциально бесконечную (т.е. делается цикл) последовательность [n,2n,3n,...], ищем в ней первое вхождение числа m, для которого ds(m)=n.
Оптимизация: составляем ряд (а по факту цикл) не с n, а с f*n, т.е. [f*n,(f+1)*n,...], где f выбирается из соображения, например, что f*n не меньше e(n), где e(n) — минимальное число, для которого ds(e(n))=n. e(n) состоит из: e mod 9 — первая цифра, далее (n div 9) девяток. Кликните здесь для просмотра всего текста
Составляем потенциально бесконечную последовательность чисел, для которых ds=n, причём отсортированных в порядке возрастания. Первый элемент — e(n).
Далее ищем первое вхождение числа, которое делится на n. Оптимизация: поскольку речь идёт о длинных числах, то можно подготовить последовательность mods=[1 mod n, 10 mod n, 100 mod n, 1000 mod n, ...] и сохранить в памяти, тогда m mod n по модулю n будет совпадать со свёрткой m как последовательности цифр [m0,m1,m2,...] и mods, т.к. Основная проблема: слишком затратно по времени. Например, очень тяжелыми оказываются n=101 и n=202, про случаи, когда n кратно 5, 25 или по-другому не взаимопростое со степенью десятки, вообще можно отдельно говорить. Например, второй метод не срабатывает, если n mod 9=1, а истинное решение имеет на одну цифру больше e(n). Тогда истинное решение стоит на позиции ~p^9, где p — число цифр e(n), а это где-то 20-50. Помогите пожалуйста, я вообще иссяк в идеях, а нужно очень срочно.
1
|
|
| 04.12.2013, 15:21 | |
|
Ответы с готовыми решениями:
47
Из 8 различных цифр составить число, делящееся на любую из этих цифр
|
| 16.12.2013, 03:13 | |
|
Вроде что-то нащупал. Сначала проверим базовое утверждение - иначе все мои дальнейшие рассуждения неверны. Структура "элемента"
key1 - сумма цифр key2 - остаток от деления на n value - число Утверждение: если есть минимальное value c ключами key1 и key2, то все остальные value (c теми же ключами) можно отбрасывать, в оптимальное решение они не войдут. Доказательство 0xxx (некоторое число) yyyy (большее число с той же суммой цифр и тем же остатком) Предположим оптимальное решение получено из большего, напр aayyyy. Но тогда есть решение aa0xxx, значит aayyyy оптимальным не является. Отсюда вытекает что все нужные комбинации лежат в мапе n*n, макс миллион эл-тов, по нынешним временам размер пионерский. Как строить эту мапу есть соображения, но давайте по порядку
0
|
|
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
||
| 16.12.2013, 10:22 | ||
|
0
|
||
| 16.12.2013, 12:55 | |
|
Тогда получается та же "задача о монетках" (демо динамического программирования). Просто-напросто "добавляем след цифру". С нуля неинтересно, там все монотонно, возьмем напр 4-ю цифру
1000, key1 = 1, key2 = 1000 % n Комбинируем этот ключ со всеми имеющимися (их не так уж много). Напр был ключ 999 (key1 = 27, key2 = 999 % n). Складывая получаем key1 = 28, key2 = (key1 + key2) % n и значение 1999. Если такой ключ уже существует с меньшим значением - ничего не делаем, иначе обновляем/пополняем мапу. Эту операцию повторяем всего для 9 чисел (1000...9000) - все, 4-й разряд готов
0
|
|
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
|
| 16.12.2013, 13:10 | |
|
Я тоже вроде динамику придумал: d[len][sum][mod] - первая цифра в минимальном числе из len цифр (лидирующие нули разрешены) с суммой цифр sum и остатком от деления на n равным mod.
Igor3D, у тебя та же идея, а то я что-то в описании запутался?
1
|
|
| 16.12.2013, 15:31 | |
|
В аттаче реализация для unsigned long long (21 цифра), т.е. используются только штатные средства языка. Поскольку ищет вполне быстро, особо не оптимизировал.
Не по теме: Что-то притих научный работник :)
1
|
|
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
|||||||||||||||||||||
| 16.12.2013, 20:12 | |||||||||||||||||||||
Самый длинный результат для 1000: 1999999999999999999999999999999999999999 9999999999999999999999999999999999999999 99999999999999999999999999999999000 так что MAXL можно уменьшить до 128, например. Для больших чисел работает не очень быстро. Возможно, надо как-то ускорять. Добавлено через 40 секунд PS: Что за магия форума со вставками пробелов в текст и код??? Добавлено через 4 минуты Оптимизация цикла - надо перенести проверку наверх:
Кстати, думаю что можно как-то длину просчитывать за логарифм, а не линейно. Правда тогда непонятно, как восстанавливать число... Добавлено через 2 часа 27 минут Небольшое упрощение того же цикла:
0
|
|||||||||||||||||||||
|
|
|||||||
| 16.12.2013, 22:31 [ТС] | |||||||
|
Что-то у меня голова не соображает: ничего не понимаю, что вы двое предлагаете.
Не по теме: Минутка ворчания:
Igor3D, я так и не понял описание алгоритма; с кодом разбираюсь, но это потребует времени. Что такое ключи? Это функции? Или свойства чисел? Как они заполняются? Покажите, пожалуйста, как идейно работает алгоритм на примере какого-нибудь простого числа, например, 23 или 73. (но Ваш код я не понял совсем)
0
|
|||||||
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
||||||||
| 16.12.2013, 22:57 | ||||||||
|
Наговорить много можно, а работающая программа - это всегда хорошо. К тому же, словами я выше сказал, что она делает. ![]() Плюс, он ограничивается типом uint64, что не даст вычислить значения для больших чисел. На просчёт всех чисел от 1 до 1000 уходит около 14 мин. На всякий случай, обознаяения:
1
|
||||||||
| 17.12.2013, 10:42 | ||||||||
|
Смысл алгоритма - тупо накапливаются все числа (фактически "пути") в двумерном массиве n х n. Строка соответствует сумме цифр, столбец - остатку. На первый взгляд это ужасно и абсурдно - но в том-то и дело что "минимальных" чисел оказывается не так уж много, их макс кол-во не превышает n^2. Теперь "почему 100"? Дело в том что проверять 101 не нужно - оно уже проверено как комбинация 100 и одного из имеющихся. Также не нужно проверять никого из 101..199, след проверка для 200. Аналогично нужно проверять только 1000, 2000,... 9000 и.т.д. Поэтому главный цикл в псевдокоде выглядит так
) Об остальном напишу в след посте
1
|
||||||||
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
||
| 17.12.2013, 11:06 | ||
|
0
|
||
| 17.12.2013, 11:32 | ||||||||||||
На самом деле такого ограничения я не выдвигал, просто сделал упрощенную реализацию. Понятно что можно (и нужно) хранить путь не целиком (как у меня), а в виде цифра + ключи + индекс предыдущей ячейки в таблице. Тогда вырисовывается такая структурка
По поводу оптимизации. Вы месите "всю таблицу", мне показалось лучше дополнительно накапливать пути в отдельном контейнере. Таблица может быть слабо заполнена (по крайней мере на первых шагах, а для n = xxx5 вообще). Кстати я печатаю заполненность. По поводу такого кода.
2
|
||||||||||||
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
|||||
| 17.12.2013, 13:39 | |||||
|
Хотя, я точно не могу сказать, не сделает ли тут что-то подобное сам компилятор... Надо посмотреть внимательнее твой код. Добавлено через 6 минут
Надо использовать long double (там 65), и то в VS всё равно не прокатит. По крайней мере в VS2005. Хотя это всё равно неактуально, поскольку надо больше цифр.
0
|
|||||
| 17.12.2013, 16:09 | ||
|
Разобрался с остатками, вариант для всех 1000 чисел в аттаче. Все вполне "цивильно", ничего не выжимал, нормальные структуры данных, контейнеры, поэтому полагаю скорость не сильно упадет при переводе на шарп. Первые 500 считаются 45 сек, последние 10 уже минуту - на совсем не новой машине.
![]() А задачка-то совсем простая оказалась - а вначале выглядело непостижимо
1
|
||
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
||||||||
| 17.12.2013, 20:23 | ||||||||
|
Тем не менее, ничего нечитаемого в коде нет. По крайней мере, для человека знающего Си++. Надо было поставить обожаемые всеми i, j, k, l и код бы от этого стал просто замечательным? Или будет классно с вот такими именами? И не только пробелы, но и отступы, причём вертикальные - тоже. PS: Я вполне допускаю, что моё решение неоптимально, однако не стоит придираться к нему просто так. Я же не придираюсь к твоему ![]() Добавлено через 13 минут Сорри. Время работы вполне нормальное всё-таки. Последние считаются примерно в 2 раза медленнее чем у меня, всё в целом - в 1.5 раза медленнее. Хотя не уверен в условиях проверки, возможно на самом деле деле немного лучше.
0
|
||||||||
| 17.12.2013, 20:40 | |
|
Не по теме: Mysterious_Light, может могу помочь? Только не пойму условие вашей задачи.
0
|
|
|
|
|
| 17.12.2013, 21:18 [ТС] | |
|
Вроде бы я понял суть алгоритма, но не до конца понял некоторые тонкости его реализации у Igor3D и Qwertiy, потому что они пишут на неизвестном мне языке. Некоторые идиомы я понимаю, некоторые — не сразу.
Например, я взял за основу последнее решение Igor3D, потому что тот код читается проще (Qwertie, не обижайтесь, но Ваш код действительно ориентирован на людей, знающих язык) В этом решении сейчас стоит проблема исключения побочных действий: функция Check не является чистой, она меняет vec; кроме того, есть таблица tbl, которая используется (считывается определенный элемент) в Check, но я не приложу ума, где она заполняется и модифицируется. На пальцах понимаю алгоритм так: делается динамика по len, rem и sum, в порядке возрастания len. Если честно, мне ещё не очевидно быстродействие этого алгоритма, потому что здесь 4 цикла, один делает 10 итераций (т.е. O(1)), два делают O(n) итераций, один делает ~n/9 итераций, итого, сложность O(n^3). Мне нужно понять решение. Поскольку я использую чистый функциональный язык, понимание, как производится контроль данных в решении Igor3D, мне крайне желательно. tolimadokara, спасибо за желание, но не думаю, что Вы можете помочь, разве что объяснить то, что я описал выше.
0
|
|
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
||
| 18.12.2013, 00:40 | ||
|
Mysterious Light, верно, ассимптотика моего алгоритма ровно кубическая. Тем не менее, время работы приемлимое, насколько я понимаю. Ассимптотику алгоритма Igor3D'я я оценить не пробовал. Возникает подозрение, что хуже моей, поскольку на больших значениях разница существеннее, чем на маленьких. С другой стороны, учитывая что в его реализации используются стандартные контейнеры, можно предположить, что его алгоритм будет работать быстрее при некотором изменении реализации.
Igor3D, мне пришла в голову идея использовать ленивую динамику для вычислений. Кажется, что это позволит свести ассимптотику к квадратичной - чисто заполнение матрицы n*n. Но не совсем уверен в этом. Что думаешь? Добавлено через 2 часа 31 минуту
1
|
||
| 18.12.2013, 10:39 | |||||
|
Таблица tbl инициализируется на старте, Cell имеет конструктор который будет выполнен для каждого эл-та, т.е len = 0. Ф-ция Check обновляет таблицу. Удобно думать "ячейка = путь". Вообще все гораздо проще если забыть о "числах" - в действительности они здесь не играют никакой роли, даже наоборот, сбивают с толку Mysterious Light, такой вопрос (не совсем корректный, просто игнорируйте если не хотите отвечать). Да, это конечно интересно, и, чего скрывать, я получил удовольствие найдя решение. Но кому это нужно? Какие практические применения для этой задачи? Так, "зарядка для хвоста"? Добавлено через 22 минуты
0
|
|||||
|
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
|
|
| 18.12.2013, 15:52 | |
|
Ещё мысли. Считать моим методом, но заменить размерность с длиной элементом структуры результата "позиция". Почему? Добавление лидирующего нуля позволяет сохранить сумму и остаток от деления, причём очевидно, что это число минимально. Значит нет смысла ставить что-то ещё. Это уменьшит расход памяти, но не скажется на ассимптотике, поскольку при обработке каждой ячейки надо будет ставить цифры во все позиции, а не в одну.
1
|
|
| 19.12.2013, 17:24 | |
|
Да, возможен на порядок (минимум) более быстрый алгоритм, правда заметно более сложный. Соображения такие:
по-прежнему храним в таблице только минимальные (мин) пути, только заполняем их иначе. Пусть у нас уже есть какие-то мин пути (неважно откуда, хоть первые неск цифр посчитали как сейчас). Тогда известна строка таблицы с макс суммой цифр. Теперь начинаем след цифру не с 1, а с 9 и пытаемся "срастить" ее не со всеми, а лишь с макс строкой. При этом мы имеем полное право обновлять таблицу как обычно - ведь никто из оставшихся 1..8 не может достичь той же суммы цифр. Также если в процессе найдено решение - оно минимально, опять-таки потому что ни у кого такой суммы цифр еще нет. Покончив с девяткой мы не берем 8, а сразу устремляемся к след разряду - и опять все вышесказанное справедливо. Так мы очень быстро пробегаем все девятки и упираемся в ситуевину когда след 9 дает уже сумму цифр большую чем надо. Что дальше я не придумал, но принцип ясен - "спуск вниз": - пусть 9 было сложено со строкой напр 120, сумма 129. Тогда на след шаге надо покончить с суммой 128. Это та же 9 + строка 119 и 8 + строка 120. После этого опять "лезем вверх" до упора. Опять не вышло, парим сумму 127 и.т.д. Эх, если бы "для дела" - вдохновения бы прибавилось, а так - баловство
0
|
|
| 19.12.2013, 17:24 | |
|
Массив: Определить, имеется ли в массиве хотя бы одно число, делящееся на 7 и не делящееся на 4 Верно ли, что, удалив одну из его цифр, можно получить число, делящееся на 3? Определить функцию расчета суммы цифр натурального числа, найти число с большей суммой цифр Найти разность между суммой цифр на четных и суммой цифр на нечетных местах Дано натуральное число n. Найти и вывести все числа в интервале от 1 до n − 1, у которых сумма всех цифр совпадает с суммой цифр данного числа. Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала.
Ниже прикреплён. . .
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
|
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
|
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ
Основная суть и тезисы по измерениям:
0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема.
Объект не может перемещаться в 0D.
1D (Первое измерение):. . .
|