|
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
|
||||||||||||||||
Алгоритм перебора разных комбинаций простых чисел18.09.2016, 13:14. Показов 4667. Ответов 7
Метки нет (Все метки)
Доброго времени суток! Решаю разнообразные задачки по программированию, попалась вот такая:
Определим функцию P(n,k) следующим образом: P(n,k) = 1, если n может быть представлено в виде суммы k простых чисел (простые числа в записи могут повторяться, 1 не является простым числом) и P(n,k) = 0 в обратном случае. К примеру, P(10,2) = 1, т.к. 10 может быть представлено в виде суммы 3 + 7 или 5 + 5, а P(11,2) = 0, так как никакие два простых числа не могут дать в сумме 11. Определим функцию S(n) как сумму значений функции P(i,k) для всех i и k, таких что 1≤i≤n, 1≤k≤n. Таким образом, S(2) = P(1,1) + P(2,1) + P(1,2) + P(2,2) = 1, S(10) = 20, S(1000) = 248838. Решение я накидал, что называется, "в лоб", о чем вскоре пожалел: Кликните здесь для просмотра всего текста
Если при значении n в S(n) все работает прекрасно, то при увеличении n скорость вычислений падает в разы (при n = 50 я так и не дотерпел до завершения вычислений). Самой первой мыслью стало перестать в P() каждый раз заново проверять числа на isSimple(). Если мы заранее знаем наше n, можно бы сделать массив заранее отобранных простых чисел до n включительно, и работать с ним во всех итерациях. На скорую руку накидал вот это: Кликните здесь для просмотра всего текста
И скорость упала еще сильнее... В общем, кажется, тут нужно кардинально менять подход. Подскажите пожалуйста, в какую сторону мне лучше двигаться, что-бы оптимизировать алгоритм. Добавлено через 13 часов 40 минут Чуть чуть допилил, стало на ~10% быстрее, но все еще не сулит перспективы посчитать для больших чисел
0
|
||||||||||||||||
| 18.09.2016, 13:14 | |
|
Ответы с готовыми решениями:
7
Реализовать генератор простых чисел с использованием решета Эратосфена и перебора делителей Алгоритм перебора комбинаций Алгоритм перебора комбинаций 1,2,3-х местных комнат |
|
Диссидент
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
|
|
| 18.09.2016, 14:20 | |
|
4elovek37, Я бы пошел таким путем.
Пусть нам надо вычислить функцию S(n) для всех n <= N Сначала составляем список всех простых <=N p1, p2, ... Заводим матрицу M[N, N] (по сути она битовая, но для начала можно char) Обнуляем ее. Теперь составляем всевозможные суммы из k=1,2, N слагаемых из этих pi (перебор можно сделать с помощью битовой шкалы) Естественно, рассматриваем суммы <= N. Пусть m - очередная такая сумма. Устанавливаем M[k,m] = 1 Дальше нам надо просто посчитать сумму единиц в соответствующем квадрате.
0
|
|
|
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
|
|||||||
| 18.09.2016, 15:22 [ТС] | |||||||
|
Байт, хм, витало что-то такое в голове еще вчера, но почему-то ушел от этой мысли, решив что будет слишком муторно. Буду пробовать.
p.s. Как и хотел, с воем коде заменил постоянную проверку isSimple() на работу с заранее созданным массивом простых. Стало работать на ~60% быстрее, но проблему это не решило, считает все еще слишком долго. Если кому пригодится (что вряд ли), в спойлере код. Кликните здесь для просмотра всего текста
Добавлено через 8 минут Байт,
0
|
|||||||
|
Диссидент
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
|
|||
| 18.09.2016, 15:45 | |||
|
0
|
|||
|
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
|
||||||
| 18.09.2016, 16:05 [ТС] | ||||||
|
От временного упадка настроения из-за собственной глупости, решил прикрутить вывод промежуточных результатов в консоль и заметил одну очень важную закономерность. Очевидно, что основную нагрузку дают вычисления при больших k, т.к. мы перебираем оочень много вариантов комбинаций простых чисел. Но начиная с k = n/2 за весь вывод программы такие проверки давали только false. Я с самого начала догадывался, что при таких "ненормальных" соотношениях маловероятны true результаты, поэтому прикрутил вот такую проверку:
1
|
||||||
|
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
|
||
| 18.09.2016, 16:22 [ТС] | ||
|
Из задачи:
0
|
||
|
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
|
|||||||
| 19.09.2016, 22:41 [ТС] | |||||||
|
Мне вновь не понравилось как медленно все работает, и я сел и, покопавшись в логе программы, оптимизировал алгоритм, теперь для n = 1000 считает за 0.0730 сек. Почему я так не мог сделать ранее - одному б-гу известно. Вот финальный вариант кода (решений в интернете для этой задачи нет, так что кому-то я этим могу помочь).
1
|
|||||||
|
Диссидент
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
|
|||
| 20.09.2016, 12:43 | |||
![]() Добавлено через 12 часов 19 минут 4elovek37, посмотрел твой последний код. Впечатление самое благоприятное. Хороший рекурсивный алгоритм. Оформление грамотное. Код прозрачен, легко читается и понимается. Пара очень мелких замечаний. Имхо, строки 39-40 можно выбросить. Также под вопросом строки 41-42. Неоправданное использование типа long. Все твои числа с большим запасом помещаются в обычный int. Размер массива simpleArr вполне можно взять N/2+1. Хватит навярняка. Но это все, конечно, мелкие мелочи. Удачи! Добавлено через 51 минуту 4elovek37, А вот замечание уже по делу. Тебе приходится многократно вычислять P(i, j) для одних и тех же значений аргумента. Может быть имеет смысл все таки завести матрицу char PP[N][N]. Забить ее, скажем, двойками (признак того, что значение не вычислено) И считать дальше, только если PP[i][j]==2. А как подсчитано, ставить 0 или 1 и в дальнейшем использовать. Недостаток такого подхода - памяти много надо. Массив [1000][1000] еще ничего. Но дальше будет хуже. Отсюда 2 выхода. 1. Хранить массив во внешней памяти (файле) 2. Создать массив PP[K][K], K < N. И брать значения из него при i, j < K. В противном случае таки считать...
2
|
|||
| 20.09.2016, 12:43 | |
|
Помогаю со студенческими работами здесь
8
Упростить код перебора комбинаций Оптимизировать код перебора комбинаций Алгоритм генерирования случайных комбинаций чисел по определенному правилу Вычисление НОД двух чисел методом последовательного перебора (Алгоритм, анализ, сложности) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога
Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&d=1772460536
Одним из. . .
|
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
|
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
|
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
|
|
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога
Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
|
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование
. \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json>
Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом.
# Check if. . .
|
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так:
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347
Основана на STM32F303RBT6.
На борту пять. . .
|
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
|