6 Ферзей — конкурс
Автор: ZealintАпр 12
Время: 4 недели (12 апреля — 10 мая 2010 г.) Конкурс завершён. Смотрите итоги.
Продолжаю делать конкурсы для программистов-математиков. Это второй конкурс. Предыдущий был посвящён перемножению матриц, и результатами я был очень доволен. Судя по отзывам, некоторые участники тоже. На этот раз задача чуть сложнее, а призовой фонд 3000 р. (на два призовых места: 2000 р. + 1000 р.). Задача довольно специфическая: сколькими способами можно расположить на шахматной доске размером n×n шесть не бьющих друг друга шахматных ферзей? Предупреждаю, решать эту задачу «в лоб» не получится, конечно, если у Вас нет под рукой мощного кластера. Но если Вы хорошо разбираетесь в переборных задачах, то участвуйте!
В чём смысл и кому это нужно?
Такого рода задачи относятся к категории так называемых «общих проблем науки». Это задача перечислительной комбинаторики. Все задачи из этой области, которые легко решаются перебором, уже давно решены, поэтому сейчас сражение идёт не за то, у кого кластер мощнее, а за то, кто умнее сможет организовать подсчёт. Решениями таких задач разные научные коллективы демонстрируют друг другу свои возможности. Сама по себе она, конечно, не имеет практической пользы, но смысл в том, что при решении таких задач иногда возникают новые методы, идеи и даже целые теории, которые затем дополняют текущую научную картину Мира. Например, когда решали задачу о расстановке n ферзей на доске n×n для n=26, разработали несколько новых теорий, на которых защитилось несколько человек.
Месяц назад была актуальной проблема пяти ферзей, но мне удалось вывести общую формулу, закрыв этот вопрос. К сожалению, пока я эту формулу упрощал, ещё один исследователь её опубликовал, причем в неупрощённом виде. Формулу можно посмотреть в энциклопедии целочисленных последовательностей: A108792 (моя формула проще, так как не содержит тригонометрических функций). Это, конечно, замечательно, но следующим шагом может быть только решение задачи о шести ферзях. Решить задачу — это значит вывести формулу или предложить другой эффективный способ получения ответа для любого значения n. Вот этим я и занимаюсь. Задачу я решу в любом случае, но конкурс поможет сделать это правильно и лучше. Все-таки, в одиночку можно и ошибиться, а когда решаешь вместе с кем-то, то вряд ли.
Что нужно для вывода формулы? Нужно получить примерно 80 чисел, тогда можно угадать закономерность. Для 5 ферзей мне нужно было знать ответ лишь до n=38.
Положения
Общие правила и ограничения
Прошлый конкурс очень сильно ограничивал участников. Например, не могли участвовать любители Linux и специалисты по параллельным вычислениям. На этот раз ограничений почти нет: делайте что хотите, считайте на чём угодно и как угодно. Побеждает тот, кто предоставит ответ для наибольшего возможного значения n. В целях борьбы с беспределом кое-какие ограничения все же будут.
- Предоставляя ответ для некоторого n участник обязан сказать ответ также для всех значений k<n. Разумеется, не надо повторять те числа, которые уже записаны в таблице результатов ниже. Например, если лидер сказал ответ для n=20, а Вы посчитали до n=23, то ответ засчитывается только если Вы также называет ответ для n=21 и n=22.
- Победители конкурса обязуются предоставить мне полный исходный код (не важно, на каком языке, только, пожалуйста, не на эзотерическом типа BrainFuck : ) ) после его окончания.
- Я, автор конкурса, тоже принимаю в нём участие на равных с остальными. Почему? Объясню ниже.
- Конкурс завершается 10 мая 2010 г. ровно в 12 ч. 00 м.
- Приз можно получить только через Яндекс.Деньги или WebMoney.
- Я оставляю за собой право менять правила проведения конкурса, если в них обнаружатся неточности.
Порядок проведения конкурса
- Во время проведения конкурса участники посылают на электронный адрес «zealint.comp@gmail.com» письмо с темой «6 Ферзей — Конкурс». В письме необходимо указать свой ник, значение n, для которого был посчитан ответ и сам ответ. Также требуется указать, на чём выполнялось вычисление (сколько ядер) и сколько минут (или часов (или дней)) заняли расчёты для указанного n.
- Будет вестись рейтинговая таблица, в которой указываются все участники и их результаты.
- Чтобы переместиться по рейтинговой таблице вверх, нужно указать ответ для того значения n, которое больше, чем у текущего лидера. То есть, если у лидера n=20, то Вам надо как минимум сказать ответ для n=21, иначе попытка не засчитывается.
- Почта проверяется случайным образом (не меньше одного раза в сутки), поэтому может возникнуть ситуация, когда несколько участников предоставляют одно и то же число, но кто-то раньше, а кто-то позже. В этом случае сравнивается дата попадания письма в ящик конкурса.
- Победителем считается тот, кто назвал ответ к задаче для наибольшего возможного n, а также прислал полный исходный код программы по истечении конкурса. За победу 2000 р.
- Второе место занимает тот, кто окажется в финальной рейтинговой таблице под номером два (если под номером два тот же, кто и под номером один, то берётся следующая позиция и т. д.) и пришлёт полный исходный код программы по окончании конкурса. За второе место 1000 р.
Гарантии
Я гарантирую, что победитель(и) получит(ат) приз в соответствии с правилами. Я уже проводил конкурсы и никого обманывать не собираюсь. Во-вторых, участие бесплатное и никто ничего не теряет. Заметьте, что я не запрещаю пользоваться самыми продвинутыми на сегодняшний день средствами программирования, в том числе кластерами. Мне нужны только ответы. Не надо, пожалуйста, думать, что я ищу дешёвую рабочую силу. Поверьте, мне не надо сдавать курсовую или диплом или что-то кому-то продавать. Да, согласен, приз не очень большой. Ну а сколько по-вашему получает преподаватель университета? Единственное, что может быть не очень честно: участники конкурса не будут указаны в научной статье об этой задаче, если я такую когда-нибудь напишу. Чтобы потом никто не обижался! Хотя ссылку на эту страницу, где все перечислены, я попробую сделать, если позволит рецензент.
Пожелания
По мере проведения конкурса привлекайте новых участников. Мой блог не так сильно раскручен, поэтому участие хотя бы 10 человек я буду считать большим успехом. Не надо думать, что этим конкурсом я оптимизирую блог (как меня обвинили в прошлый раз). Если бы я хотел это сделать, то на 3000 р. просто купил бы ссылок.
После окончания конкурса я, по вашему желанию, установлю ссылки с этой страницы на главные страницы вашего сайта, при условии, что Вы установите ссылку со своей не главной страницы на эту. Все ссылки без noindex и nofollow.
Если пишете комментарии, то подписывайтесь тем ником, который у вас отображается в таблице рейтинга (если отображается).
FAQ
Некоторые участники форумов программистов начинают задавать одни и те же вопросы (или высказывать соображения), на которые тяжело отвечать одно и то же. Поэтому делаю список часто задаваемых вопросов. Сюда входят даже те вопросы, которые ещё никто не задал, но хотел.
- Что за тупой конкурс? Ответ: идите нафиг.
- Вы правда думаете, что за 3000 р. люди сразу побегут к вам писать программы? Ответ: не нравится — не участвуйте. Конкурс не для всех, а для тех, кому интересно писать оптимальный код. Мне думается, что промышленные программисты и web-программисты не должны тратить на это время.
- А у меня под рукой сто тысяч ядер, я напишу тупейший перебор и всё равно выиграю! Ответ: посмотрим : ) Я совершенно не ограничиваю Вас в выборе инструмента. Да, отчасти тут есть элемент неравенства, особенно если Вы имеете доступ к кластеру. Но работу мозга ещё никто не отменял. Так даже интереснее: мозги против железа! А у кого есть и то и другое… в общем, посмотрим. Самому интересно, что будет.
- Я 5 лет работаю программистом и понятия не имею как решать эту задачу, если только не перебором. Ответ: программисты бывают разными, например, web-программисты и т. д. Конечно же, если Вы не понимаете в чем состоит задача и почему в ней надо думать — это конкурс не для Вас. Это для тех, кто умеет писать оптимальный код для вычислительных задач, то есть для тех, кто на этом специализируется. Конечно же этим конкурсом я не хочу обидеть остальных программистов, которые сильны в какой-то своей области. Это просто не для них и всё.
- Как Вы собираетесь проверять ответ? Ответ: скорее всего, к концу конкурса я выведу формулу, как сделал это месяц назад для задачи о пяти ферзях. В любом случае, я с большой вероятностью могу сказать, правильное дано число или нет. Поэтому, кстати, и требую помимо одного числа указать все предшествующие.
- То, что Вы являетесь участником и организатором дает Вам те или иные преимущества — это нечестно. Например, вдруг Вы уже вывели формулу? Ответ: ничего подобного. Да, у меня есть опыт решения трудных задач. Если бы я вывел формулу, то уже давно опубликовал бы её, а конкурс бы сделал для семи ферзей. Единственное моё преимущество в том, что до начала конкурса я уже написал перебор и посчитал с его помощью несколько чисел. Они опубликованы на этой странице ниже. Подумайте, кстати, почему я проиграл в прошлом конкурсе? Всё честно, а если Вам что-то не нравится, просто не обращайте на меня внимания и покиньте эту страницу. Разойдёмся с Миром.
- А если я выведу формулу, что делать? Ответ: когда выведете, тогда и поговорим. Если кто-то выведет формулу раньше окончания конкурса, то он завершится досрочно, а автор формулы, видимо, победит.
- Это «баян». В интернете полно исходников, мы в школе ещё эту задачу делали. Ответ: Даже если Вы в школе что-то делали, то максимум до n=10 или 15 (для совсем продвинутых). Эту задачу ещё никто не решил. В Интернете Вы не найдете ничего такого, что позволило бы Вам продвинуться хоть немного. «Баяном» это станет тогда, когда будет предоставлена явная формула. А сейчас такого рода рассуждения не более чем
трёппустой разговор.
Текущий рейтинг
Таблица ниже будет постоянно обновляться по мере поступления новых чисел. Внимание: прежде чем присылать число, убедитесь, пожалуйста, что до Вас его ещё никто не вывел. Удачи!
Таблица участников
Конкурс завершён.
- Zealint :: 07.05 :: n = 80 :: 56 ядер (2,6 GHz) :: 10 ч.
- Zealint :: 07.05 :: n = 75 :: 56 ядер (2,6 GHz) :: 6 ч. 6 м.
- Zealint :: 06.05 :: n = 70 :: 64 ядра (2,6 GHz) :: 2 ч. 53 м.
- Zealint :: 05.05 :: n = 60 :: 60 ядер (2,6 GHz) :: 53 м.
- Zealint :: 05.05 :: n = 55 :: 55 ядер (2,6 GHz) :: 30 м.
- Zealint :: 04.05 :: n = 54 :: 8 ядер (2,6 GHz) :: 2 ч. 20 м.
- alexBlack :: 03.05 :: n = 53 :: 1 ядро (1,6 GHz) :: 13 ч. 15 м.
- alexBlack :: 01.05 :: n = 52 :: 1 ядро (1,6 GHz) :: 16 ч.
- alexBlack :: 30.04 :: n = 51 :: 2 ядра (2,9 GHz) :: 5 ч. 10 м.
- Zealint :: 29.04 :: n = 50 :: 64 ядра (2,6 GHz) :: 26 ч. 34 м.
- Zealint :: 26.04 :: n = 42 :: 8 ядер (2,6 GHz) :: 33 ч. 25 м.
- alexBlack :: 24.04 :: n = 41 :: 2 ядра (2,9 GHz)::17ч. 20м. (с 38 по 41)
- alexBlack :: 24.04 :: n = 40 :: 2 ядра (2,9 GHz) ::
- alexBlack :: 24.04 :: n = 39 :: 2 ядра (2,9 GHz) ::
- alexBlack :: 24.04 :: n = 38 :: 2 ядра (2,9 GHz) ::
- alexBlack :: 23.04 :: n = 37 :: 2 ядра (2,9 GHz) :: 4 ч. 20 м.
- Zealint :: 23.04 :: n = 36 :: 8 ядер (2,6 GHz) :: 4 ч. 53 м.
- Zealint :: 22.04 :: n = 35 :: 2 ядра (3 GHz) :: 16 ч. 14 м.
- alexBlack :: 21.04 :: n = 34 :: 1 ядро (2,9 GHz) :: 4 ч.
- alexBlack :: 19.04 :: n = 33 :: 1 ядро (2,9 GHz) :: 4 ч. 10 м.
- alexBlack :: 19.04 :: n = 32 :: 1 ядро (2,9 GHz) :: 3 ч.
- alexBlack :: 18.04 :: n = 31 :: 1 ядро (1,6 GHz) :: ~8 ч.
- alexBlack :: 18.04 :: n = 30 :: 1 ядро (1,6 GHz) :: ~8 ч.
- Zealint :: 16.04 :: n = 29 :: 1 ядро (2,6 GHz) :: 6 ч. 6 м.
- alexBlack :: 15.04 :: n = 28 :: 1 ядро (2,9 GHz) :: 3687 с.
- alexBlack :: 15.04 :: n = 27 :: 1 ядро (2,9 GHz) :: 2602 с.
- alexBlack :: 15.04 :: n = 26 :: 1 ядро (2,9 GHz) :: 1706 с.
- Zealint :: 15.04 :: n = 25 :: 1 ядро (3 GHz) :: 5405 с.
- Zealint :: 14.04 :: n = 24 :: 1 ядро (3 GHz) :: 3798 с.
- alexBlack :: 13.04 :: n = 23 :: 1 ядро (1,6 GHz) :: 2052 с.
- alexBlack :: 13.04 :: n = 22 :: 1 ядро (1,6 GHz) :: 1123 с.
- alexBlack :: 13.04 :: n = 21 :: 1 ядро (1,6 GHz) :: 654 с.
- Zealint :: 12.04 :: n = 20 :: 1 ядро (2,67 GHz) :: 1680 с.
- Zealint :: 12.04 :: n = 15 :: 1 ядро (3 GHz) :: 130 с.
Для ориентира: программа, которая считала ответ для n=15 работала со сложностью O(n12). Для n=20 уже работала программа со сложностью O(n11). Чтобы ориентироваться в сложности лучше, можно обсуждать время работы программ в комментариях.
Таблица значений
- 4
- 832
- 22708
- 312956
- 2716096
- 17117832
- 84871680
- 349093856
- 1239869972
- 3905117168
- 11139611892
- 29224290600
- 71402912960
- 164029487484
- 357164398040
- 741835920276
- 1477798367368
- 2836053660668
- 5263672510684
- 9478352925488
- 16606678238496
- 28378012168908
- 47398421913600
- 77522788818316
- 124365738451680
- 195977208395580
- 303748457927000
- 463582807382736
- 697434075907504
- 1035256352634420
- 1517521355687872
- 2198354851112760
- 3149525540545556
- 4465340754179496
- 6268789672000200
- 8718985543275112
- 12020393279930400
- 16433877629761792
- 22290259302807700
- 30006374870365136
- 40104595602917300
- 53235736336244300
- 70206658745546392
- 92012392107526748
- 119874540287319196
- 155285624835663096
- 200061731591400456
- 256402868739653996
- 326964160566718884
- 414936937933564876
- 524143826614930088
- 659146400314780240
- 825370726096096944
- 1029248723087783480
- 1278382175175730400
- 1581726455456457436
- 1949802708715765760
- 2394934394370749612
- 2931519277634600260
- 3576331321283597364
- 4348866396076652064
- 5271724407012487004
- 6371045245979662116
- 7676988784016499040
- 9224280528369282176
- 11052810248193489712
- 13208310203912865056
- 15743096674420482872
- 18716907492532573788
- 22197814778572880876
Следите за конкурсами на моём блоге. Дальше будет сложнее и интереснее.
Информационные спонсоры
КиберФорум — форум начинающих и профессиональных программистов, системных администраторов, администраторов баз данных. Компьютерный форум.
Клуб ПРОграммистов — Форум программистов.
dxdy — Научный форум.
Обсуждение конкурса на форуме в этой теме.
Число комментариев: 61
Комментарий от on 13.04.2010 - 13:11
не понимаю, как можно получить синусы в целочисленной формуле
Комментарий от on 13.04.2010 - 16:57
наклепал алгоритм
но с вашими результатами расходится
у меня такая таблица:
6 — 4
7 — 2328
8 — 65028
есть ли таблица для пяти фигур, чтобы я мог проверить свой алгоритм?
Комментарий от on 13.04.2010 - 17:13
Я же дал ссылку на энциклопедию, где есть последовательность с пятью ферзями: . Там можно также отыскать 4 и 3 фигуры. И 2 наверно есть.
Комментарий от on 14.04.2010 - 08:24
я увидел там несколько аргументов или параметров и ничего не понял
а свой алгоритм я уже исправил, теперь считает как у вас
Комментарий от on 14.04.2010 - 09:29
Там просто автор криво формулу написал. Когда переходите по ссылке, нужно сдвинуться по странице максимально влево. Там увидите последовательность: 10, 248, 4618, 46736, 310496… Первое число в ней — это для n=5.
Комментарий от on 14.04.2010 - 11:15
На самом деле, до начала конкурса ответ для 24 у меня уже был (я просто не хотел, чтобы сразу большие числа появились, дал только 20 для затравки). Ещё 11 апреля была заявлена последовательность , которая появилась в энциклопедии только сегодня утром. Добавлять туда числа дальше нет смысла. Наша задача — вывести формулу. Если кто раньше выведет, сможет её туда дописать.
Комментарий от on 14.04.2010 - 15:53
Интересный конкурс. С удовольствием бы поучаствовал, если бы обладал нужными навыками такой оптимизации. Увы, я web-программист, потому мое дело — кодить сайты =)
А вот ссылочку разместить на конкурс — это мы всегда с радостью =)
Комментарий от on 15.04.2010 - 09:54
Zealint, я вас не совсем понял
Конкурс продолжается со старыми правилами?
Или теперь нужно искать формулу?
Комментарий от on 15.04.2010 - 10:59
Все продолжается по-старому! Просто я сказал, что если кто выведет формулу, тот молодец : ) Тот сможет обессмертить своё имя в энциклопедии. А так, считаем дальше… Я, вот, уже до 25 досчитал, но метод решения явно тупиковый.
Комментарий от on 16.04.2010 - 18:03
Да уж, даже если за сутки посчитает 30, то дальше безнадёжно. Надо переходить к алгоритму за O(n^10) и только так. Кстати, а где специалисты по CUDA?
Комментарий от on 18.04.2010 - 08:03
Товарищи, скажите хотя бы, в чём проблема? Почему никто не может (или не хочет) посчитать следующее число? Например, я сейчас думаю над значительным ускорением алгоритма. А в чём проблема у остальных потенциальных участников? Через страницу прошло где-то 200 человек… и только один что-то посчитал…
Комментарий от on 18.04.2010 - 21:13
Первые 3 числа верные.
У меня пока,ч то алгоритм делает полный перебор
Комментарий от on 20.04.2010 - 09:36
У меня проблема только в лени переписывать свой алгоритм с Lua на C
А на Lua считает слишком долго, все-таки скриптовый язык
Комментарий от on 20.04.2010 - 18:57
Есть просьба к администратору. Т.к. мне затруднительно определить производительность своего компьютера, то нельзя ли предоставить EXE-файл, для какого нибудь одного значения — например n=20.
Комментарий от on 21.04.2010 - 07:55
Тов. kahey, по условиям конкурса имеет смысл присылать ответы (или решения) только для тех значений, для которых ещё никто не посчитал. В противном случае нет гарантии, что Вы просто не написали в программе что-то вроде print ( 357164398040 ) и все. Кстати, если Вы не можете определить скорость процессора, можете её и не указывать. Только укажите, на скольки ядрах считали.
Комментарий от on 21.04.2010 - 14:51
а я вообще не понимаю
вы для каждого размера поля пишите отдельный алгоритм?
Комментарий от on 21.04.2010 - 15:24
Нет, конечно. Алгоритм один, просто работает долго. В данный момент я считаю n=35 алгоритмом, работающим за O(n10) и одновременно с этим думаю, как ускорить программу хотя бы в 10-15 раз. Или надо переходить к O(n9). Либо пойду на кластере считать.
Комментарий от on 21.04.2010 - 15:58
У меня производительность компьютера слабая.
Мне интересно сравнить эффективность алгоритма.
Чисто для себя. Потому, что если мой алгоритм хуже, то мне не угнаться.
Комментарий от on 21.04.2010 - 17:43
Ну если хотите, присылайте мне письмо с Вашей программой, я протестирую на процессоре E-8400 (3 GHz).
Комментарий от on 21.04.2010 - 23:58
Спасибо, но я уже понял, что моей оптимизации оказалось недостаточно.
Чтобы увеличить скорость потребуется сделать предыдущие вычисления — думаю это это займёт слишком много времени.
Комментарий от on 22.04.2010 - 12:17
вот [url=http://rznusl.ucoz.ru/dialog/frz91.rar]программа[/url] — она не считает количество позиций и, даже, не выполняет частичную задачу. Но процесс вычисления в ней очень схож с моим алгоритмом.
Мне бы хотелось узнать время выполнения расчёта на Вашем компьютере.
При запуске надо нажать на кнопку. У меня время счёта составило несколько минут.
Комментарий от on 22.04.2010 - 14:00
У меня Ваша программа работала 64 секунды. Что-то вывела, я не запомнил.
Комментарий от on 22.04.2010 - 15:20
Ясно, у меня она работала 330 секунд (в 5 раз дольше)
Комментарий от on 23.04.2010 - 03:03
Нескромный вопрос: а что вы используете в качестве, длинной арефметики?
Комментарий от on 23.04.2010 - 07:27
Пока влезает в long long (64 бита со знаком). Скоро перейду на 128 бит со знаком (нужно соединить два 64-битных числа и правильно отслеживать перенос из младшего в старшее, благо что в моём алгоритме только сложение)
Комментарий от on 26.04.2010 - 07:31
Ну и дела, программа совсем резко замедляется. Если не перейти к O(n9), ничего не получится.
Комментарий от on 26.04.2010 - 15:52
А что подразумевается под O(n^9), это что-то типа девяти вложенных циклов от 1 до n?
наконец, переписал свою программу на C, но для n=30 она считает сутки, хотя циклов у меня меньше 9-ти
Комментарий от on 26.04.2010 - 16:32
Не совсем. Это означает, что программа выполняет не больше C*n9 операций, где C — любое конечное число, большее нуля. В моём случае это действительно будет девять вложенных циклов. Сейчас их 10.
Если у Вас меньше девяти циклов, то это не означает, что Ваш алгоритм эффективнее, так как, например, может быть рекурсия или вызов какой-нибудь неэффективной функции. Можно взять профилировщик и посмотреть, где узкое место.
Чтобы хоть примерно узнать показатель степени при n, можно поделить время работы для n=30 на время работы при n=15 и взять двоичный логарифм от полученного частного. Для надёжности надо проверить на другой паре чисел, отличающихся вдвое. Это будет не точно, но хоть примерно.
Комментарий от on 26.04.2010 - 20:55
Если 9 вложенных циклов друг вдруга, то скорость можно увеличить.
У меня один и тотже алгоритм работает в различной реализации — разница где-то 1.25 раза.
Комментарий от on 27.04.2010 - 07:49
Думаю, 1.25 раза недостаточно. Мне пришлось ускорять последнюю версию программы в 9-10 раз. И этого всё равно мало. Для n=20 работает уже 190 с. Ну а для 42 получается полторы машинных недели. Отсюда и название: труднорешаемая задача. Ну ничего, формулу пробьём! До 10 мая ещё есть время.
Комментарий от on 28.04.2010 - 16:26
Интересно, а каким методом была получена формула для 5-ти ферзей? Насколько я понимаю, то что она верна, всего лишь гипотеза
Комментарий от on 28.04.2010 - 17:03
Формула верна и это доказано. В комбинаторике существует ряд методов, с помощью которых можно вывести формулу для любого n, если знать подряд идущие начальные данные. У меня есть вариант формулы для 5 ферзей, которая не содержит тригонометрических функций. Выводил я её из рекуррентного соотношения, а соотношение получается из первых 38 значений. Всё это делается строго и 100% верно. Там в энциклопедии все формулы правильные. Вот если у меня будет много денег, я сделаю конкурс по «угадыванию» формул, там же напишу теорию, которую участники смогут использовать для получения правильного результата. Разумеется, задачи будут такими, которые ещё никто не решил, но пытался.
Вы же понимаете, что я не могу в комментариях полностью расписать весь метод, о котором Вы спросили : )
Комментарий от on 29.04.2010 - 09:42
В ход пошла тяжёлая артиллерия. 50 считалось больше суток на 64 ядрах. На 49 было ровно сутки. Пока не придумал, как считать более эффективно (по порядку). Ещё немного и наступит переполнение 64-битовой арифметики.
Комментарий от on 29.04.2010 - 09:55
Ваш алгоритм, как Вы его описываете, явялется полиномиальным. С другой стороны, для классической задачи расстановки N ферзей на доске NxN известны только экспоненциальные алгоритмы (включая те, которые используют симметрии). Возможно ли применить Ваши идеи для разработки полиномиального алгоритма и для классической задачи ?
Ведь для нее известны только 26 первых чисел, а вывод формулы не поддался даже Гауссу. Если — нет, то в чем принципиальная разница между алгоритмами решения текущей задачи и классической ?
Комментарий от on 29.04.2010 - 10:45
Принципиальная разница в том, что это две совершенно разные задачи. Между ними такая же пропасть как между величинами nk и nn. В первом случае k фиксировано (как и наше число ферзей), во втором случае степень тоже переменная, а это уже другой класс функций – гипергеометрические. 6 ферзей решаются за полиномиальное время, так как из всегда шесть. А n ферзей… я не знаю, существует ли экспоненциальный, как Вы сказали, алгоритм (я такого не видел), но если решать моим способом, то будет гипергеометрическое время (типа n факториал), что гораздо больше, чем любая экспонента. Грубо говоря, замена k на n приведёт к тому, что мы попадаем в другой класс последовательностей. На сегодняшний день интересным остаётся вопрос: существует ли способ записать формулу для такого рода задач, не выходя за пределы известной математики? Возможно, задача об n ферзях может быть записана как определитель какой-то хитрой матрицы конечного порядка, но этого пока никто не знает. Если гипотеза верна, то это ещё очень даже хорошо.
Короче, Вы ведь понимаете разницу между k циклами из n итераций и и n циклами из n итераций? Сейчас задача об n ферзях без помощи теории групп не решается вообще, поэтому наоборот, было бы неплохо применить ИХ алгоритмы к ЭТОЙ задаче. Наоборот делать нет смысла.
Комментарий от on 29.04.2010 - 14:11
я не понимаю каким методом можно вывести формулу
чем вы пользовались? Дайте ссылку, если возможно
Комментарий от on 29.04.2010 - 15:14
Меня уже столько раз об этом спрашивают, что, видимо, придётся по этому поводу делать отдельную статью. Не существует способа, который годился бы для всех задач. Для этой задачи (уже доказано) существует линейное однородное рекуррентное соотношение с постоянными коэффициентами. Например, для трёх ферзей это соотношение 9-го порядка: a(n) = 5a(n — 1) — 8a(n — 2) + 14a(n — 4) — 14a(n — 5) + 8a(n — 7) — 5a( n — 8 ) + a(n — 9). Для четырёх порядок уже 17, для пяти — 37, для 6 где-то 75-80. Чтобы отыскать коэффициенты в этом соотношении, нужно решить систему линейных уравнений, где неизвестными являются эти самые коэффициенты, система строится, если подставлять в неизвестное соотношение уже известные ответы. Если порядок соотношения равен 9, то нужно 18 первых чисел. НО! В этой задаче точно известно, что знаменатель производящей функции (в неупрощённом виде) имеет вид (1-z)N, где N – порядок. Из этого следует, что мне надо всего лишь N+1 первое число, а не 2N, как в общем случае.
Ссылку дать не могу. Эти вещи не обсуждаются в учебной литературе. Только в научных статьях, да и то, совершенно не связанных с нашей задачей. А бесплатно Вы их вряд ли найдёте. Статьи стоят около 30$ на научных сайтах.
Видимо, я напишу об этом серию статей в будущем. Но данная тема требует знания комбинаторики не меньше, чем дают в университете на факультете математики. Если бы все это было так просто, то, как Вы понимаете, задача была бы давно решена. А задачи, которые уже решены, сейчас решать малоинтересно.
Комментарий от on 29.04.2010 - 15:52
Вот, вспомнил ещё, что в Maple есть функция rgf_findrecur, которая по заданной последовательности ищет формулу. В версии 12-13 есть функция listtoratpoly, которая даёт рациональную производящую функцию по начальному отрезку ряда.
Комментарий от on 29.04.2010 - 16:32
можно придумать сколько угодно формул для каждой конечной последовательности чисел
вопрос в том, чтобы она была верной
Комментарий от on 29.04.2010 - 18:32
Совершенно верно. Поэтому «угаданная» формула доказывается отдельно. Обычно для каждой задачи понятно, какой вид должна иметь формула. А если вид известен и угаданная формула этому виду соответствует, то она верна. Теория, которая лежит в основе всех этих рассуждений слишком длинная, чтобы её писать в комментариях. Но будьте уверены, что она правильная. Когда-нибудь напишу подробно, и все станет понятным.
Комментарий от on 30.04.2010 - 18:00
64 ядра -это, что, уже такие компьютеры появились?
Комментарий от on 30.04.2010 - 18:37
Это кластер у меня.
Вот тов. alexBlack без всякого кластера быстрее считает. Молодец! Я сейчас думаю над созданием алгоритма со сложность n в 9-й. По идее, если смотреть за временем, у alexBlack именно такой (или даже быстрее). Мне надо сесть и, наконец, дописать его.
Другие потенциальные участники могли бы поделиться, докуда им удалось посчитать. Просто интересно.
Комментарий от on 02.05.2010 - 14:01
Артем, а под каким компилятором ты запускаешь свои программы? например для n = 15 пример?
А то у меня сложность решения O(n^10), но для 12 уже работает минуты 3 на AMD 3.2 ГЦ, скомпиленным под GNU 3.4.2
Комментарий от on 02.05.2010 - 14:02
А да, еще вопрос, у тебя решение сразу отсекает 6! повторных перестановок, или делишь ответ на 6! ?
Комментарий от on 02.05.2010 - 14:16
А все, туплю, избавился от 5! действий….работает действительно быстро!!!!
Комментарий от on 02.05.2010 - 14:19
Чувствую, что для 55+ уже будет нужна длинная арифметика….сложность умножится на большую константу!
Комментарий от on 02.05.2010 - 15:13
Моё решение за O(n10) для n=15 работает 6 с половиной секунд. Для n=20 — 190 с. Разумеется, никаких 6! нет и быть не должно.
Вовсе не обязательно писать длинную арифметику, достаточно соединить два 64 битных числа для получения 128-битовой арифметики. Сразу хочу сказать, что 50 я тоже считал за 10-ю степень. Это долго. Не советую повторять : )
Сейчас тестирую другой подход, за 9-ю степень. Считаю всё сначала, чтобы проверить. Есть идея как перейти к O(n8), но пока не вижу необходимости.
Компилятор Intel С++ 11. В данной задаче это не так важно. Visual Studio здесь тоже работает быстро.
Комментарий от on 04.05.2010 - 17:33
Запустил другой алгоритм, работающий за О(n7). Ещё не оптимизировал сам код, раз в 10 точно можно ускорить. Работает долго, но замедление гораздо ниже.
Комментарий от on 05.05.2010 - 09:55
Ладно, т.к. не хватает времени на участие в конкурсе, опишу свой алгоритм.
Чтобы сгенерировать все расстановки 6 ферзей, на поле n*n можно сгенерировать два массива:
1. массив длинной C_n^6, каждый элемент которого это шесть чисел — участвующие в расстановке строки или столбцы
2. массив длинной 6!, каждый элемент которого это шесть чисел — всевозможные расположений фигур в выбранных 6-ти строках и 6-ти столбцах
Теперь организуем тройной цикл:
в первом выбираем комбинацию строк из первого массива
во втором — комбинацию столбцов из того же массива
в третьем конкретное положение фигур
осталось проверить, чтобы в выбранной комбинации фигуры стояли на разных диагоналях
Но этот алгоритм легко сократить
Во первых, будем считать, что в расстановке всегда участвует первая строка и столбец, тогда в первом массиве будет С_(n-1)^5 элементов и вводим память — будем запоминать количество комбинаций не бьющих друг друга ферзей в расстановках в пределах u строк*w столбцов с участим крайних строк, столбцов, т.е. комбинации шириной u*w.
Вот первые 4 строки «памяти» (на Lua),
local mem={
[6]={[6]=4,},
[7]={[6]=86,[7]=472,},
[8]={[6]=366,[7]=2216,[8]=8692},
[9]={[6]=1286,[7]=7426,[8]=27024,[9]=76424,},
}
Во вторых, третий цикл будем выполнять не 6! раз, а 6!/2 из-за симметрии.
В результате первый цикл пробегает C_(n-2)^4 элементов генерируя только комбинации в которых используются крайние столбцы, второй цикл пробежит, как уже сказано, С_(n-1)^5 элементов, а третий 6!/2.
Проходя эти циклы, проверяем на диагонали и заполняем новую строку «памяти». По «памяти» легко получить, то что требуется в конкурсе.
Но этот метод оказался долговат
Есть другой метод, до которого я не доберусь уже до конца конкурса.
Память можно заполнять и другим способом. Чтобы сгенерировать все комбинации шириной u*w можно перебрать все возможные координаты 5-ти ферзей, и складывать количество не битых 5-ю ферзями клеток (и левее 5-го ферзя). При этом из 10 координат 5-ти ферзей 4 координаты фиксированы, т.к. у нас заданна ширина комбинации u*w. Получается примерно 6 циклов от 1 до n. А сложность алгоритма около O(n^7).
Спасибо за внимание
P.S.
Еще есть метод для расчета длинных досок (комбинации шириной u*w, где u примерно в два раза больше (меньше) w), но это уже не важно
Комментарий от on 05.05.2010 - 13:48
В предпоследнем варианте (с 5-ю ферзями) можно еще учесть группы симметрии (по верхнему и угловому ферзям). После отсечения лишних вариантов в большинстве случаев найденное количество не битых клеток умножается на 4, остальные на 2 или 1 (очень мало). У меня почти так,
только не битые клетки считаются по последним двум ферзям (из шести).
Комментарий от on 05.05.2010 - 13:56
Спасибо за описание. Неплохой способ, и числа такие же у меня получаются. Идея с граничными условиями точно такая же, подробнее напишу в отдельном посте. Только моя программа работает совсем без массивов. Точнее, есть два массива, но в каждом 6 элементов, можно не считать.
Через некоторое время я выведу формулу для этой задачи, но, к сожалению, доказать её сразу не смогу. Она будет правильной, без сомнения, но для строгого доказательства нужно считать где-то 144-145 чисел. А для вывода достаточно будет 80.
Комментарий от on 06.05.2010 - 07:30
Ответ для n=70 уже не помещается в 64 бита со знаком. Зато без знака пока влезает.
Комментарий от on 06.05.2010 - 08:30
Ну, вот, идея у всех одна, а побеждает тот, у кого ядер больше
Комментарий от on 06.05.2010 - 17:49
У меня наверное другая идея.
1) Я использовал оджин массив. Для ускорения счёта возможно нажо использовать не двухмерный массив. а одномерный.
2) Суть подсчёта в перестановке фигур конечно, но для ускорения счёта можно воспользоваться предыдущими расчётами. Я использовал только удвоение (симметрия). Пытался применить подход, когда число умножается на 4, но этот алгоритм не отработал.
Комментарий от on 07.05.2010 - 07:47
Для n=74 ответ уже не влезает в 64 бита без знака. Но поскольку программа выводит не ответ, а лишь промежуточные данные (из которых собирается ответ), то на самом деле длинная арифметика и здесь не нужна. Промежуточные данные — это где-то n2 чисел размером всего по 15-16 знаков.
Комментарий от on 08.05.2010 - 11:36
У меня на сайте есть программа, которая умеет скалывать большие числа.
Комментарий от on 08.05.2010 - 12:35
Интересно, что в треугольнике 4,86,366…/472,2216…/8692,27024… для
каждой строки выполняется равенство
a(n)-5a(n-1)+10a(n-2)-10a(n-3)+5a(n-4)-a(n-5)=0, n >= 5m-6
здесь m — номер строки треугольника. К сожалению n>=5m-6 это слишком далеко для практических вычислений. Подобные закономерности наблюдаются и для другого количества ферзей (знаки чередуются, а коэффициенты берутся из треугольника Паскаля). Например, для трех ферзей:
a(n)-2a(n-1)+a(n-2)=0, n>=2m+1
Комментарий от on 08.05.2010 - 20:37
Все правильно, тов. alexBlack. Для первых нескольких строк можно проверить. Я тоже удивился, что закономерность простая (такое редко получается), однако даже если так, то насчитать начальные члены ряда всё равно сложно. А их много. То есть в любом случае это не очень помогает.
А моя программа считает всё дольше и дольше… На 80 надо 10 часов. Для верности я подожду 81. Кажется, закономерность замыкается. Значит, формула к концу конкурса будет. Без доказательства.
Комментарий от on 09.05.2010 - 13:42
Если считать по формуле, то быстрее получится. Попробую её доказать математически.
Комментарий от on 09.05.2010 - 21:19
Завтра напишу пост, в котором будет формула и идея моего решения задачи. К вечеру постараюсь успеть. Ещё нужно подвести итоги, наградить участников : )
Комментарий от on 10.05.2010 - 10:34
Просьба сообщать мне заранее о предстоящем конкурсе — я буду делать соответствующую ссылку у себя на сайте.