![]() |
|
![]() ![]() ![]() |
|
Chingachguk |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1232 Регистрация: 25.3.2002 Где: Москва Репутация: 1 Всего: 18 |
Моя прога на turbo pascal 7.0, компьютер был P-120. Числа до 300 считает примерно ~5-6 секунд легко. Если выделять больше памяти на хранение количеств разложения чисел на суммs только через простые числа, не большие 23, 29, 31 ... и т.д., то можно добиться и большего. Просто требуется выделение памяти. (Смотри мои массивы: P3:array[0..MaxValidNumber] of longint; P5:array[0..MaxValidNumber] of longint; ... P23:array[0..MaxValidNumber] of longint и их заполнение в процедуре Sum_NumberBest) -------------------- I don't like the drugs (but the drugs like me). M.Manson. |
|||
|
||||
Alex101 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 891 Регистрация: 8.4.2002 Где: Москва Репутация: 1 Всего: 10 |
Когда проверяете, является ли число простым, то надо в качестве делителей числа N перебирать до sqrt(N) - уже на этом время сэкономите.
2 ChinqachqukИнтересный у тебя алгоритм, но слишком громоздкий. -------------------- С уважением, А. Фролов. |
|||
|
||||
Alex101 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 891 Регистрация: 8.4.2002 Где: Москва Репутация: 1 Всего: 10 |
Интересная задачка!
Сейчас что-то влом вызовы отлавливать, завтра-послезавтра точно решу. -------------------- С уважением, А. Фролов. |
|||
|
||||
Chingachguk |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1232 Регистрация: 25.3.2002 Где: Москва Репутация: 1 Всего: 18 |
Время определения простоты числа тут некритично. Я довольствовался сравнением: делиться на 2 ? на 4 ? (битовые операции) - даже про 8 не стал писать. Хотя с корнем интересно, я не знал этого. Алгоритм не громоздкий, он просто очень тупо написан (массивы PNN[] нужно было слить в один и сделать цикл по уже двумерному массиву) - чего громоздкого, это всего лишь одна рекурсивная процедура - первая процедура (Sum_Number) вообще приведена для примера, ее можно замочить ;) -------------------- I don't like the drugs (but the drugs like me). M.Manson. |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 33 Всего: 110 |
по-моему, решение олимпиадной задачи не должно быть длинным...
не обращайте внимания на процедуру определения простоты числа (мне просто лень писать что-то сложнее, а идея алгоритма состоит не в этом)
Это сообщение отредактировал(а) maxim1000 - 9.9.2006, 22:16 -------------------- qqq |
|||
|
||||
Chingachguk |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1232 Регистрация: 25.3.2002 Где: Москва Репутация: 1 Всего: 18 |
Гм. Что-то я не вижу отличия от моего решения ;)
Все та же рекурсия - но только без оптимизации. Так, например, если заменить integer->longint, то она почти мгновенно считает writeln(quantity(100,2));, но вот с writeln(quantity(200,2)); конкретно замирает - и это на P800 ! У меня считало нормально на P120 до 300 ж) -------------------- I don't like the drugs (but the drugs like me). M.Manson. |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 33 Всего: 110 |
Прошу прощения, не разобрался в этом коде и сразу начал писать свой...
Просто мне хотелось сделать сам алгоритм понятным (по-моему, так и должно быть на олимпиадах). -------------------- qqq |
|||
|
||||
Chingachguk |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1232 Регистрация: 25.3.2002 Где: Москва Репутация: 1 Всего: 18 |
Да фигня ;) интересно, что у тебя выйдет, если ты попробуешь для серьезных чисел посчитать Ж)
-------------------- I don't like the drugs (but the drugs like me). M.Manson. |
|||
|
||||
Chingachguk |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1232 Регистрация: 25.3.2002 Где: Москва Репутация: 1 Всего: 18 |
Вот, написал на Паскале для дос то же самое, но более аккуратно, с выделением памяти. Позволяет секунд за 5 на P800 сосчитать для чисел около 1000. Дальше надо либо с расширенной памятью (dpmi и тд) возиться, либо с диском ;)
Примечание: из-под среды не пойдет (не хватит памяти), надо пускать экзе.
-------------------- I don't like the drugs (but the drugs like me). M.Manson. |
|||
|
||||
Kuvaldis |
|
|||
![]() механик-вредитель ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1189 Регистрация: 16.6.2006 Где: Минск Репутация: 1 Всего: 61 |
Нашел еще красивое решение (используется динамическое программирование)
-------------------- Помни - когда ты спишь, враг не дремлет Спи чаще и дольше, изматывай врага бессоницей |
|||
|
||||
Executer |
|
|||
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 4.8.2006 Репутация: нет Всего: нет |
Это стандартная задача на динамическое программирование.
Вот общий агоритм: 1. Найдем все простые числа. 2. Затем начнем строить все разложения. Посмотрим на простом примере 2 = 2 3 = 3 4 = 2 + 2 5 = 2 + 3 6 = 2 + 2 + 2 6 = 3 + 3 Как можно подсчитать количество разложений числа 6? А вот как - посмотрим количество разложений числа 6 - 2 и числа 6 - 3, и сложим их. От сюда выстраивается дп алгоритм. Перебираем все числа от 0 до N, и во вложенном цикле ищем количество разложений для данного числа, заканчивающегося данным простым числом. А вот программа на java: (Кстати количество разбиений будет очень велико, поэтому надо брать последнии цифры числа, для числа 5000 программа работает меньше секунды на P4 3.0 Ghz)
|
|||
|
||||
IvanoffAndrey |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 157 Регистрация: 8.7.2006 Где: СГАУ Репутация: нет Всего: 2 |
Я бы пробовал искать формулу.
GoldMan, Попробуйте найти функцию f(x), x=есть разлогаемое число, а f - возвращает количесто разложений. Обычно на аллимпиадах местного масштаба редко загибают сложно - переборные задачи (часто ставят ограничение по времени - и перебор не проходит), поэтому наверняка есть иное решение. Наверняка эт формула будет связана с арифметическим треугольником. Щас посижу, попробую, если получится у меня сообщу. --------------------
Размерность пространства есть число Pi и в каждой точке вселенной оно стремиться к этому числу. |
|||
|
||||
nostromo |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 194 Регистрация: 23.3.2006 Репутация: 5 Всего: 10 |
To IvanoffAndrey: мне кажется Вы слишком упрощаете ситуацию и нерекурсивное алгебраического выражения для этой функции найти очень сложно. Кстати, известный метод треугольника Паскаля можно рассматривать как частный случай метода динамического программирования.
To Kuvaldis, Executer: Ваш метод мне в общем понятен, однако в правильности реалзации не уверен. Если не сложно, приведите пожалуйста значения, которые выдают ваши программы, скажем, для чисел 7, 20 и 1000. Добавлено @ 08:28 Да, Executer, как Ваша программа могла посчитать ответ для 5000, если уже ответ для 1400 не влазит в 8-байтное целое, а длинную арифметику Вы, судя по коду, не используете? |
|||
|
||||
Kuvaldis |
|
|||
![]() механик-вредитель ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1189 Регистрация: 16.6.2006 Где: Минск Репутация: 1 Всего: 61 |
Код на Pascal - с сайта УрГУ. Думаю, что там правильно.
Вот лично мой вариант (программа все тесты на моей универской олимпиаде прошла)
Я тесты прикрепляю (правда, у нас было ограничение для входящего числа <= 330, но все же) Это сообщение отредактировал(а) Kuvaldis - 13.9.2006, 10:40 Присоединённый файл ( Кол-во скачиваний: 2 ) ![]() -------------------- Помни - когда ты спишь, враг не дремлет Спи чаще и дольше, изматывай врага бессоницей |
|||
|
||||
nostromo |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 194 Регистрация: 23.3.2006 Репутация: 5 Всего: 10 |
То Kuvaldis:
посмотрел результаты --- похоже правильные (с моими, по крайней мере, совпадают). Привожу до кучи и свою реализацию на языке Smalltalk (VisualWorks). Суть алгоритма в следующем. Пусть есть число X и простое число P. Ставится задача нахождения всех вариантов представления X в виде суммы простых слагаемых, каждое из которых не превосходит P. Эта задача рекурсивно сводится к себе с меньшими параметрами: func(X,P) = func(X-P, P) + func(X, предыдущий(P)) (псевдокод) Идея подобна приводившимся ранее, однако данная ее реализация имеет свои преимущества (прежде всего, простота). Комментарии к реализации. Чтобы избежать повторных вычислений в рекурсивных вызовах, найденные значения сохраняются в словаре memoDict. Работа с простыми числами идет по индексам из предварительно составленного списка простых чисел.
Счет можно запускать так: N := 4000. index := (Integer primesUpTo: N) size. res := worker func: N lastIndex: index. Вот избранные ответы: 7: 3 20: 26 1000: 48278613741845757 4000: 1629425615961660388014828752394491 В последнем случае счет занял около 6 минут на P4 (для динамически типизированного языка с учетом длинной арифметики я считаю --- нормально) и словарь memoDict содержал 650641 элементов --- кажется, это меньше, чем требуется приведенным здесь реализациям метода динамического программирования для такого входного аргумента. Добавлено @ 12:32 Забыл, перед запуском расчета, конечно, нужно создать экземпляр класса: worker := Solver new. --------------------
На пыльных тропинках далеких планет останутся наши следы. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Алгоритмы" | |
|
Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Алгоритмы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |