From 0e6e6ec83394f0a278eb825d4a6e940ebbc1608f Mon Sep 17 00:00:00 2001 From: Aleksey Lobanov Date: Thu, 26 Oct 2017 18:06:45 +0300 Subject: [PATCH] HTTPS for Google fonts --- archives.html | 2 +- archives.html.gz | Bin 1646 -> 1647 bytes author/aleksei-lobanov.html | 2 +- author/aleksei-lobanov.html.gz | Bin 4404 -> 4404 bytes authors.html | 2 +- authors.html.gz | Bin 1098 -> 1099 bytes categories.html | 2 +- categories.html.gz | Bin 1086 -> 1087 bytes category/misc.html | 2 +- category/misc.html.gz | Bin 2965 -> 2965 bytes category/proekty.html | 2 +- category/proekty.html.gz | Bin 2359 -> 2360 bytes category/project-euler.html | 2 +- category/project-euler.html.gz | Bin 3143 -> 3145 bytes feeds/all.atom.xml | 170 +----------------- feeds/all.atom.xml.gz | Bin 3363 -> 3308 bytes feeds/all.rss.xml | 170 +----------------- feeds/all.rss.xml.gz | Bin 3486 -> 3332 bytes feeds/feed.atom.xml | 170 +----------------- feeds/feed.atom.xml.gz | Bin 3362 -> 3306 bytes feeds/feed.rss.xml | 170 +----------------- feeds/feed.rss.xml.gz | Bin 3484 -> 3332 bytes feeds/misc.atom.xml | 58 +----- feeds/misc.atom.xml.gz | Bin 1902 -> 1887 bytes feeds/proekty.atom.xml | 2 +- feeds/proekty.atom.xml.gz | Bin 1175 -> 1213 bytes feeds/project-euler.atom.xml | 114 +----------- feeds/project-euler.atom.xml.gz | Bin 2104 -> 2055 bytes feeds/tag-bgl.atom.xml | 2 +- feeds/tag-bgl.atom.xml.gz | Bin 651 -> 665 bytes feeds/tag-blog.atom.xml | 2 +- feeds/tag-blog.atom.xml.gz | Bin 489 -> 502 bytes feeds/tag-bot.atom.xml | 2 +- feeds/tag-bot.atom.xml.gz | Bin 516 -> 529 bytes feeds/tag-c.atom.xml | 58 +----- feeds/tag-c.atom.xml.gz | Bin 2092 -> 2080 bytes feeds/tag-flint.atom.xml | 56 +----- feeds/tag-flint.atom.xml.gz | Bin 1639 -> 1612 bytes feeds/tag-go.atom.xml | 2 +- feeds/tag-go.atom.xml.gz | Bin 550 -> 564 bytes feeds/tag-lichess.atom.xml | 2 +- feeds/tag-lichess.atom.xml.gz | Bin 523 -> 534 bytes feeds/tag-matematika.atom.xml | 56 +----- feeds/tag-matematika.atom.xml.gz | Bin 1574 -> 1544 bytes feeds/tag-open-source.atom.xml | 2 +- feeds/tag-open-source.atom.xml.gz | Bin 554 -> 569 bytes feeds/tag-proekt.atom.xml | 2 +- feeds/tag-proekt.atom.xml.gz | Bin 1176 -> 1213 bytes feeds/tag-project-euler.atom.xml | 114 +----------- feeds/tag-project-euler.atom.xml.gz | Bin 2106 -> 2058 bytes feeds/tag-python.atom.xml | 56 +----- feeds/tag-python.atom.xml.gz | Bin 1725 -> 1697 bytes feeds/tag-shakhmaty.atom.xml | 2 +- feeds/tag-shakhmaty.atom.xml.gz | Bin 667 -> 685 bytes feeds/tag-sympy.atom.xml | 56 +----- feeds/tag-sympy.atom.xml.gz | Bin 1722 -> 1697 bytes feeds/tag-wallabag.atom.xml | 2 +- feeds/tag-wallabag.atom.xml.gz | Bin 551 -> 565 bytes feeds/tag-wxwidgets.atom.xml | 2 +- feeds/tag-wxwidgets.atom.xml.gz | Bin 633 -> 648 bytes index.html | 2 +- index.html.gz | Bin 4380 -> 4380 bytes pages/about.html | 2 +- pages/about.html.gz | Bin 1813 -> 1821 bytes pages/projects.html | 2 +- pages/projects.html.gz | Bin 2029 -> 2031 bytes posts/crossgen-v10/index.html | 2 +- posts/crossgen-v10/index.html.gz | Bin 4470 -> 4471 bytes posts/eksport-partii-s-lichess/index.html | 6 +- posts/eksport-partii-s-lichess/index.html.gz | Bin 2852 -> 2857 bytes .../index.html | 2 +- .../index.html.gz | Bin 3610 -> 3612 bytes .../kak-ia-shakhmatnogo-bota-pisal/index.html | 2 +- .../index.html.gz | Bin 4249 -> 4251 bytes .../index.html | 2 +- .../index.html.gz | Bin 2173 -> 2174 bytes posts/moio-reshenie-zadachi-134/index.html | 4 +- posts/moio-reshenie-zadachi-134/index.html.gz | Bin 4212 -> 4218 bytes posts/moio-reshenie-zadachi-146/index.html | 4 +- posts/moio-reshenie-zadachi-146/index.html.gz | Bin 5445 -> 5452 bytes posts/moio-reshenie-zadachi-60/index.html | 4 +- posts/moio-reshenie-zadachi-60/index.html.gz | Bin 6923 -> 6929 bytes .../index.html | 2 +- .../index.html.gz | Bin 4091 -> 4092 bytes posts/wallabag-i-realnaia-zhizn/index.html | 2 +- posts/wallabag-i-realnaia-zhizn/index.html.gz | Bin 3932 -> 3934 bytes sitemap.xml | 8 +- sitemap.xml.gz | Bin 766 -> 765 bytes tag/bgl.html | 2 +- tag/bgl.html.gz | Bin 1789 -> 1792 bytes tag/blog.html | 2 +- tag/blog.html.gz | Bin 1646 -> 1648 bytes tag/bot.html | 2 +- tag/bot.html.gz | Bin 1670 -> 1672 bytes tag/c.html | 2 +- tag/c.html.gz | Bin 3141 -> 3140 bytes tag/flint.html | 2 +- tag/flint.html.gz | Bin 2694 -> 2694 bytes tag/go.html | 2 +- tag/go.html.gz | Bin 1697 -> 1699 bytes tag/lichess.html | 2 +- tag/lichess.html.gz | Bin 1674 -> 1678 bytes tag/matematika.html | 2 +- tag/matematika.html.gz | Bin 2650 -> 2649 bytes tag/open-source.html | 2 +- tag/open-source.html.gz | Bin 1702 -> 1705 bytes tag/proekt.html | 2 +- tag/proekt.html.gz | Bin 2356 -> 2358 bytes tag/project-euler.html | 2 +- tag/project-euler.html.gz | Bin 3143 -> 3145 bytes tag/python.html | 2 +- tag/python.html.gz | Bin 2778 -> 2778 bytes tag/shakhmaty.html | 2 +- tag/shakhmaty.html.gz | Bin 1838 -> 1840 bytes tag/sympy.html | 2 +- tag/sympy.html.gz | Bin 2777 -> 2777 bytes tag/wallabag.html | 2 +- tag/wallabag.html.gz | Bin 1697 -> 1699 bytes tag/wxwidgets.html | 2 +- tag/wxwidgets.html.gz | Bin 1792 -> 1794 bytes tags.html | 2 +- tags.html.gz | Bin 1274 -> 1277 bytes 122 files changed, 87 insertions(+), 1275 deletions(-) diff --git a/archives.html b/archives.html index 2c1aa3e..0d0efd0 100644 --- a/archives.html +++ b/archives.html @@ -1,4 +1,4 @@ - Блог 529 Блог 529

Archives for Блог 529

Пн 17 Июль 2017
Экспорт партий с Lichess
Вс 30 Октябрь 2016
Моё решение задачи 134
Пт 21 Октябрь 2016
Моё решение задачи 146
Пт 22 Июль 2016
Нахождение суммы k-ых степеней
Чт 17 Март 2016
Wallabag и реальная жизнь
Вс 10 Январь 2016
Как я шахматного бота писал
Вс 02 Август 2015
CrossGen v1.0
Пт 17 Июль 2015
Моё решение задачи 60
Пт 03 Июль 2015
Ещё одно вычисление выражений
Пт 17 Апрель 2015
Мой первый пост или зачем этот блог?
Блог 529 - Алексей Лобанов
  1. Экспорт партий с Lichess

    Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.


  2. Моё решение задачи 134

    Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

    Блог 529 - Authors

    Authors on Блог 529

    Блог 529 Блог 529 - misc
    1. Нахождение суммы k-ых степеней

      Как придумать формулу для суммы \(1^5 + 2^5 + 3^5 + \ldots + n^5\) и есть ли она вообще?

      Блог 529 - Проекты
      1. Экспорт партий с Lichess

        Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.



      2. CrossGen v1.0

        Читая хабр, случайно натолкнулся на идею сделать программу, которая по заданной кроссвордной сетке находит способ её заполнить. В этом посте вкратце напишу про моё решение и первую версию приложения.


      3. Ещё одно вычисление выражений

        На хабре когда-то увидел статью про то, что в Яндексе двум сотрудникам дали задачу на написание приложения, для вычисления выражений. Менеджер справился за 4 часа, а программист за два. Я решил попробовать свои силы.


      Page 1 / 1
      Блог 529 - Project Euler
      1. Моё решение задачи 134

        Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

        Блог 529
        1. Экспорт партий с Lichess

          Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.


        2. Моё решение задачи 134

          Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

          Блог 529

          Здравствуйте, я Алексей Лобанов

          Сейчас я студент ВМК МГУ. Немного занимаюсь фрилансом и машинным обучением.

          Умею писать:

          1. Бекенды на Python (+flask)
          2. Фронтенды на jQuery
          3. Парсеры на scrapy
          4. Кроссплатформенные приложения на C++/Python с использованием wxWidgets
          5. И интегрировать во всё это машинное обучение на scikit-learn, xgboost и TensorFlow.

          Если вы хотите связаться со мной и обсудить что-нибудь, то можете выбрать удобный способ связи:


          Мои проекты
          1. Мои проекты

            Значительная часть моих проектов есть на GitHub или BitBucket вместе с открытым исходным кодом.

            CrossGen

            alt text

            Что использовалось

            1. C++
            2. wxWidgets

            Что реализовано

            1. Графический интерфейс
            2. Автоматическая локализация всего интерфейса на русский и английский языки
            3. Быстрая генерация кроссворда по заданной сетке с использованием эвристики
            4. Автоматический бенчмарк для измеренеия производительноти генерации Подробнее я писал тут

            За подробностями пишите мне на почту


          CrossGen v1.0
          1. CrossGen v1.0

            Начать, наверное, нужно с того, что реальную практическую значимость я осознал после того, как реализовал 90% того, что есть сейчас. Сейчас мне кажется, что единственное применение данного приложения лишь в том, чтобы создавать кроссворды очень сложной или необычной формы. Зачем это надо обычному человеку я вообще не знаю.

            Собственно, алгоритм генерации изначально был примитивным: простой рекурсивный поиск с отсечением. Скорость генерации более-менее сложных сеток была ужасной (для перцентиля 30% это примерно 40 минут на этой сетке, в общем случае, время генерации непредсказуемо.

            В дальнейшем были выполнены некоторые оптимизации. Первой более-менее значимой стала замена передачи сетки в юникоде (во внутреннем цикле) на передачу сетки в однобайтовой кодировке, таким образом, языки с алфавитом больше ~200 букв пролетают. Впрочем, мне кажется, что им не слишком сильно требуются кроссворды. Такая оптимизация дала ~35% прироста при значимом времени перебора (больше секунды).

            В какой-то момент, мне показалось, что оптимизация структуры данных для хранения сетки тоже могла сильно увеличить производительность, но это будет заметно только на разряженных сетках, которые и так достаточно быстро генерируются. На сложных же плотных сетках, прирост скорости может быть минимальным, вплоть до отрицательного. Таким образом, используются просто двумерный массив.

            Наибольший прирост, как и ожидалось, дало упорядочивание словаря по некоторому критерию. Таким образом, при переборе, “плохие” варианты будут попадаться редко. На это ушло немногим больше дня. В конечном итоге, целевой функцией, которая стала критерием сортировки, стала такая \(\sqrt[n]{\prod_{i=1}^{n}{f\left( a_i \right)}}\) (иначе говоря, среднее геометрическое отлично подошло), где \(n\) — количество букв в слове, \(a_i\) — буквы слова, а \(f \left( x \right)\) есть вероятность появления буквы \(x\). Я отсекаю примерно половину самых “плохих” слов, а из того, что осталось я составляю кроссворд. Производительность, в среднем, увеличилась в ~1000 раз. На тестовых сетках для перцентиля 90% длительность работы около секунды.

            Что реализовано

            • Прозрачная интернационализация (пока только русский и английский языки)
            • Быстрая генерация
            • Экспорт в текстовом формате
            • Простая смена словаря
            • Относительно простое редактирование сеток

            Что может быть реализовано

            • Визуальный редактор сетки
            • Экспорт в HTML, PDF, Markdown
            • Экспорт сетки в файл картинки

            Скриншоты

            • Версия для Xubuntu: alt text
            • Версия для Windows 7: alt text
            Экспорт партий с Lichess
            1. Экспорт партий с Lichess

              Одну партию с Lichess скачать довольно просто, это можно сделать на странице с самой игрой. Скачать все игры тоже несложно, для этого есть специальный раздел.

              Если же хочется скачать свои партии, то я нашёл лишь одно решение. Последний коммит был сделан 2 года назад, также оно не учитывает ограничения API, и больше ~2000 партий, за раз скачать не получится.

              Моей целью было написание альтернативы, которая бы работала быстрее и работала корректно.

              Проблема формата решена довольно просто: API отдаёт PGN, значит его поддержка уже есть. Но это плохой формат для хранения и обработки. Поэтому нужно было выбрать что-то ещё.

              Существует, практически, только Scid, если вы хотите хранить свои шахматные партии, используя открытый софт. В его дистрибутиве уже есть необходимые утилиты для конвертации pgn в свой формат.

              Репозиторий здесь, а здесь можно скачать файлы сразу.

              Возможности

              1. Многопоточность
              2. Сохранение как в PGN, так и в формат Scid
              3. Для работы необходим только Python
              4. Работает при любом числе партий

              Установка

              pip install grequests
              -

              Запуск

              python lichess.py -n hippo23 -t pgn -o hippo23.pgn  --threads 6 
              +        
              1. Экспорт партий с Lichess

                Одну партию с Lichess скачать довольно просто, это можно сделать на странице с самой игрой. Скачать все игры тоже несложно, для этого есть специальный раздел.

                Если же хочется скачать свои партии, то я нашёл лишь одно решение. Последний коммит был сделан 2 года назад, также оно не учитывает ограничения API, и больше ~2000 партий, за раз скачать не получится.

                Моей целью было написание альтернативы, которая бы работала быстрее и работала корректно.

                Проблема формата решена довольно просто: API отдаёт PGN, значит его поддержка уже есть. Но это плохой формат для хранения и обработки. Поэтому нужно было выбрать что-то ещё.

                Существует, практически, только Scid, если вы хотите хранить свои шахматные партии, используя открытый софт. В его дистрибутиве уже есть необходимые утилиты для конвертации pgn в свой формат.

                Репозиторий здесь, а здесь можно скачать файлы сразу.

                Возможности

                1. Многопоточность
                2. Сохранение как в PGN, так и в формат Scid
                3. Для работы необходим только Python
                4. Работает при любом числе партий

                Установка

                pip install grequests
                +

                Запуск

                python lichess.py -n hippo23 -t pgn -o hippo23.pgn  --threads 6 
                 

                Здесь hippo23 мой ник, а pgn формат сохранения (доступен также scid).



              Ещё одно вычисление выражений
              1. Ещё одно вычисление выражений

                Задачка кажется не очень сложной, даже, если не знать как её делать (я не знал). Целью является быстрое вычисление чего-то типа 4 * ( 5 + 7 ^ 4). Для это я парсил исходную строку в список токенов, а затем непосредственно вычислял, что получится.

                Я решил, что проще всего будет реализовать (а мне потом и понять) алгоритм, когда после каждого действия будет выполняться некий “хороший” инвариант. Первое что приходит в голову — это то, что истинность выражение после выполнения операции не меняется (TITO соблюдается). То есть выражение 3 + 5 можно заменить на 8 или хотя бы на 4 * 2.

                Непосредственно сама обработка является несколькими проходами, так что в каждом проходе мы избавляемся от операций одного приоритета. 4 + 5 * 3 заменяется на 4 + 15, 7 - 5 * 2^3 заменяется на 7 - 5*8. Таким образом, каждый цикл тривиален, и легко задавать приоритеты операций.

                Если использовать один список как контейнер для токенов и при работе изменять непосредственно его, сохраняя указанные инварианты, то сложность получается \(O\left( N \right)\), где \(N\) — число токенов.

                Времени на непосредственно кодирование ушло часа три-четыре, но в это время не входит продумывание мелких деталей.

                Всё написано на C++11. Исходники лежат на GitHub и BitBucket.

                Как я шахматного бота писал
                1. Как я шахматного бота писал

                  Лет 5 назад я достаточно активно играл в живые шахматы. Потом времени на это стало не хватать и постепенно перешёл на редкие партии в онлайне. Сейчас для игры я использую одно из самых популярных приложений вк. Это проще, чем использовать, к примеру, FICS. Предмет обсуждения появился из-за того, что я как-то раз встретился с соперником, который на все ходы потратил порядка 10 секунд, при этом не допустив значимых ошибок. Тогда я решил написать своего бота, чтобы узнать что с ним будет и столкнусь ли я с какими-нибудь подводными камнями.

                  Целью было максимально быстрое написание максимально простого решения. Поэтому от разбора протокола я сразу отказался, тем более у меня не было подобного опыта ранее. Была мысль работать с FICS (у меня есть библиотека для работы с их протоколом), но поскольку я там не играю, то и результаты были бы не так интересны, во всяком случае, для меня. Таким образом, я писал простого кликера для приложения вк.

                  Изначально хотелось найти доску и определить положения всех фигур, это было бы достаточно универсально, хотя и привязало бы меня к OpenCV. Тем не менее, решил не усложнять: можно определять только последний ход, а это можно сделать, проверяя цвет только одного пикселя.

                  В самом скрипте около 200 строк на python. Очень сильно помогла библиотека chess, которая взяла на себя общение с движком (я использовал stockfish), проверку на допустимые ходы и определение мата. Некоторое время я уделил тому, чтобы сделать бота максимально похожим на человека, чтобы было невозможно выявить, что это бот полностью автоматическими средствами. По пунктам:

                  • Клик по полю в случайном месте, с распределением по Гауссу, центр которого не совпадает с центром клетки
                  • Случайное время хода, длительность которого распределена по Гауссу, причём средняя длительность хода изменяется, в зависимости от номера текущего хода.
                  • Прокладываются дополнительные точки, с распределением по Гауссу, при перемещении курсора от точки к точке.

                  По факту, всё это было лишним, бан получить не удалось даже при простом клике из начальной точки в конечную.

                  Примеры работы скрипта можно посмотреть тут и тут, анализы двух сыгранных игр лежат тут и тут (оппонент имеет рейтинг около 2100).

                  На момент публикации аккаунт вполне жив. Рейтинг достиг некоторого потолка (около 2200), после которого найти игроков примерно равного рейтинга, не являющихся ботами, очень сложно. Сражаться же с ботами сильно сложнее, такую цель я не ставил. Интересно, хоть и ожидаемо, что при наборе рейтинга было достаточно личностей, для которых возможность того, что их нагло обманули, и они играли с ботом была столь неприятна, что они не могли сдерживаться. Например: alt text

                  p.s. Уже после создания рабочей версии от одного из оппонентов узнал про lichess.org. Это отличный ресурс на котором кроме, собственно, платформы для игры в шахматы (поддерживается большое количество их вариантов), есть тренировки по дебютам, анализ игр. Самое интересное — ресурс полностью открытый, все исходники есть на github.

                  В процессе подготовки данного материала узнал про InternetChessKiller, который делает, фактически, тоже самое, что и мой скрипт, но без привязки к какой-то одной игровой площадке. Исходники старых версий можно найти, например, в этом репозитории.

                  p.p.s. Боты на серверах, предназначенных для людей, играющие в игры, которые предназначены для людей очень сильно мешают людям. Тем не менее, проверять, насколько сильно они мешают не нужно!



                Мой первый пост или зачем этот блог?
                1. Мой первый пост или зачем этот блог?

                  Есть несколько причин появления этого блога. Самая главная — хочется как-то использовать домен, который я купил изначально для красивой почты. Но она не единственная. Мне также хочется делиться частью того, что я делаю на платформе, которую я могу контролировать. Ну и контактные данные. Хорошо, когда все в одном месте.

                  Пока я планирую публиковать свои, возможно не лучшие, но рабочие решения для задач из Project Euler (projecteuler.net). На самом деле, решения значительного числа задач уже есть в Сети, но на английском. Хотя, это и не есть большая проблема.



                Моё решение задачи 134
                1. Моё решение задачи 134

                  Назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

                  Например, если \(p_1 = 19\), то следующее простое \(p_2 = 23\). Тогда порождающим будет число \(1219\), при этом \(1219 \: \vdots \: 23\).

                  Полное условие можно найти тут

                  Несмотря на то, что сложность задачи 45%, для её решения достаточно выписать условие.

                  Пусть \(p_1\) содержит в себе \(k\) цифр, т.е. \(n = r \cdot 10^k + p_1\), где \(r\) — какое-то натуральное число с отрезка \(\left[ 1; p_2-1 \right]\)

                  Давайте посчитаем остатки по модулю \(p_2\): \(n \equiv r \cdot 10^k + p_1 \equiv 0\). Отсюда получим явную формулу для \(r\):

                  $$ r \equiv -p_1 \cdot 10^{-k} \equiv -p_1 \cdot 10^{p_2 -1-k} $$

                  Комментарии:

                  1. Так как \(a^p \equiv a \mod p\), то верно что \(a^{-k} \equiv a^{p -1-k} \mod p\)
                  2. Это всё бессмысленно, если не знать про алгоритм быстрого возведения в степень, который делает асимптотическую сложность возведения в степень логарифмической.

                  У нас есть явная формула для порождающего, и мы знаем как её быстро посчитать. Ниже приведён код на Python с использованием sympy.

                  from sympy import primerange  # для получения простых чисел
                  +        
                  1. Моё решение задачи 134

                    Назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

                    Например, если \(p_1 = 19\), то следующее простое \(p_2 = 23\). Тогда порождающим будет число \(1219\), при этом \(1219 \: \vdots \: 23\).

                    Полное условие можно найти тут

                    Несмотря на то, что сложность задачи 45%, для её решения достаточно выписать условие.

                    Пусть \(p_1\) содержит в себе \(k\) цифр, т.е. \(n = r \cdot 10^k + p_1\), где \(r\) — какое-то натуральное число с отрезка \(\left[ 1; p_2-1 \right]\)

                    Давайте посчитаем остатки по модулю \(p_2\): \(n \equiv r \cdot 10^k + p_1 \equiv 0\). Отсюда получим явную формулу для \(r\):

                    $$ r \equiv -p_1 \cdot 10^{-k} \equiv -p_1 \cdot 10^{p_2 -1-k} $$

                    Комментарии:

                    1. Так как \(a^p \equiv a \mod p\), то верно что \(a^{-k} \equiv a^{p -1-k} \mod p\)
                    2. Это всё бессмысленно, если не знать про алгоритм быстрого возведения в степень, который делает асимптотическую сложность возведения в степень логарифмической.

                    У нас есть явная формула для порождающего, и мы знаем как её быстро посчитать. Ниже приведён код на Python с использованием sympy.

                    from sympy import primerange  # для получения простых чисел
                     
                     # быстрое возведение в степень по модулю
                     def fast_pow(x, y, modulo):
                    diff --git a/posts/moio-reshenie-zadachi-134/index.html.gz b/posts/moio-reshenie-zadachi-134/index.html.gz
                    index cb4d06c94fb3db79a08889845e0fa61a0052d8a7..f02dc232e3c01f809f133acd8d4e9a7739459318 100644
                    GIT binary patch
                    delta 3841
                    zcmV+c5B~7ra$9$v3dr0K%w$)=!zrNaK4)?j&rQ(7g
                    zHqj^!Xxgo``hqzQYn7x_rIA!667)Se2zxQ>AIfwxyAS<6%dvm#
                    zO?}i1-5{L1$zA?qvszuBTeDn$dN#*&Hsr5cd(?**GkVO;^|^mz(&||W{>;?KO^0_<
                    z%%{Tbu%H_@i^D}jZG*BMwnKYX&^1J8wkfrJ({dcc3V6@B+jBIfQqA%_@KFo1fr)E#
                    za!rb2IRO=}6+oVn>7=d=z8HKvI2`+O%?-$7dOUD=E_S#yG
                    z6e`6LU$n9cyyJhHyO7hlFninvvg}i#FBnV4f^-MW{54bIMwT&0DZkd_c0a}AXo<`w
                    zK`*W-Dy6ptD5RQa2-xkzng0_NsAVQGY
                    zY6WZ;WFxzaqk>VlMU9&2r8SnSr=wY$?Gk1~VG*zw
                    zD!{8{ouxv~`pl+HOK7n=ajg4Y%jSD=^mIFdhh797P+eiCqr)04N*~I^7TCPI(5SJP
                    z1A|hhdmw*4bI=`FgQOh}JOY4W+cPOsC)BaHLieyL_#IFnxgI*Ojll~7b^F2aA=K$_
                    zhmWCbA41tqR09;{2BMK`?WSmljwB9~I!2a%q}E0u*GSB(oLy@S{tZNaI(QDuo(`X&
                    zyfp~KVdFo*vWua`23xkf51E
                    zY-*;Wr&0-ij*?nKCMBF3Csi{;Csw%BajngHka!swkGX9g`&7zpSNR@=kRZ)IS*4hy
                    zTq7a_Ks8fQX{byAKV~vc?QuWQv3G)Uk@ZRLi~t2#@ANFOgIS>3nA~AsaGQU=w*myf;MHs*$O;>~L;kW4u?4j*qvWW?
                    zew|^w#^66emaicOpAWwnydpK)YYe`Z;d40nKPlwr!+!y(U)4-lA~5sq@CklBA3hrX
                    zj!4)CkQ)wQ3WxywL-;Mz((p40fTS>6$zjd+tVBwz;#y;~>}^-c1t(Y`-uA-gER=sN
                    zfB{yJYLGFiZTMKK??6rhsYgIGo%~RfQjEh2{Koi)6p3p}*DsZ>Q9LljLy+c)q*N$Q
                    zN{T2+y&%JXMY^CP*eUD~7)~ZM+Kxd$(+7b6Z1_9){7UZZP;K%XAPn>$3?ISVtKlP(
                    zX93h@r2OZw)q~e5bCbDb)1mEPgS>yWLaOt>UQ%whDOjf)Y$ZaeloL6D+$E}ec)vp6
                    z6V>^mm`9yduOx&(>!|bC6Tm(wvou&@e^sRl^aSJ<7Sqc5GZskPJ;`@R0*ZWumKZ)v
                    zSwEkCbs;0_QF|8Rkj-VXxoh*l$6smr62<)&Q1~`>!beI7a5EX@ucXZ1WvzdlX`Jv7
                    z6BR~^rQL98fD>?-@6{nEXbtJ>4^{O^Y=yP~;;?o<_CMT8;`)&olDCY!$C;EvF1~fX
                    zk~q`Bk^H2hJL)fFCH=kH!}H;1U2Us1Cd<#0fClD|WJ-U2MW9+kTZt)y
                    z41X&_{go8%QS712I$*
                    zpD@aC9v6sy#1L>4fkb+Kiq~59|D8tvW19J5KL}M
                    z&piNVk@X+i`=?o2yBRP-WKfkNl)K70kk;stbb_2^5Ay=3MrHkl+AuVZ-${KAzEZ_#wI6h$
                    z7e$#d{i$$&th#?pU?!Vjth+hS5d416>r4L;Asjp95DjLG#dsHTqJw!6I&DwTMkY#H
                    z98UFcz@?g+Z^VI+2HJ78MqBV+oZK^uuA6YrSw&RV!zbDK$Xde_aJUeb+o3T;7Nk|x
                    z8fVi6i!x&3JlVcEswCi}Nl44DnZj*PTF((C9Zv^2J}rMIkNEU>O*yWB8GULEo3`_H
                    z*#;|Fez5KFy*w*=TBDpd4>q`40ADFGT7Oyu$hD!v3$SLFkEsfEg3GFdwI>OgUEo@y
                    zUe8_WF|9FQAmTI<<_IZh5DK@DYxSi2$M`ASWszRqw3CcUW}1bXSU6qBdUJYxjp7O^
                    z{j4x2PS}6X7^U;aQ_q_Tuk%w|cgpDcN!jY|PsdiT$ueoD`Vk5u_DIkn!Qmu6$bT=J
                    z^XIBSW*%*%TS~S3O!Yl@u$IqYh_1`;xy6%|$hfEQr%a4Zt$~k&r_73D?aQ$cF&N&O
                    zkm|;(L~e0H-~3q-%2ENwToJ;>B5xkK^J%&d_KttO>FkuL(x)j41W=ocqUd4yQtrWu
                    zTj)Yl_0{b}=%KDiw^wLT4mv{~mQ5jmwY0L2f)Y3gsI0ErdAZ_VawJj#?W
                    z<#W*JBnwIKIX=FK9?ks#?TXW@fTyO6*X5Za7u%XT#VzC?8w(x$)a^ZW$8eJVyEy;9
                    zt~r1HY1r}vndkVnOr@2-7q!ez-x~fzg7O53skpq)6&_Hm9l;I{Ljyx`}x_@>@2w_uMq57
                    zf>;jg;9t|U7GP7MRg%jE%(Y<(m*#0NHILS83To}(QrmKTs;#J73@DVGh#BC&m_dIT
                    zq@mO`
                    zZabDxclRs+Hyzf*JE;=aTre&f^X7j|82y8F*SO=q-QsSWb?WQ%m-^M4Yx>QbA8fzB
                    ze)9t^;8z~sjq)Doo$ndkgF_`+gSjphh=Vqf?yAjhk$PelE#~%q*fg$5cIA5-nHvG%
                    zhmvENY?N*ycccg6m9{ElkRa+ZxkrExb$!NNACW+Id65)QDmd`_y(V{jHFkgbbs@M&
                    zMjwIWw7~&v#evXILV3OPR@iG&;Uje`47eID6Qoxn`(%Gy7ElXvXRa3pCI|-P)o*2Np8~)^Py}RYk?(#(0iZropPdOg6g+dhVa18@2JpmnX|d
                    zFDAF3!R&C+k8cv{>MEhS6Q6l=Ah|~PI);Ci%wCMK39QcXI8<^m<&}^aMGgvK)g2H8
                    znp^;>kV45}88v@9jXeNG-F!cCN&d(Uf1cd%muIulf;y^AICIUYv%$7!eF9lSeu0;6
                    zY@z?+$nZkHTZZOMSgoB^=zBhf{-Crqdvu+;R@0#$Fn4DiA(`8WfXZ>^DyL6qVd`!v
                    z+haRM`h}?|c+%v38c4cSd?cXRBH>&~;dxyzVl;-Z#sYbI!v^3|H3321c0CTl3hC7C
                    zqT^46_^_BCrZEfzs-oL5Qg7>}&o{7Q`F*z~-z&lqBoiu<5x%UI>;?MW72+En9CF;?
                    z7PqOvT%U^I9SVngTJBVQxr_bTGJGcq;5hGp$rtzX-to2ANqTiWBSR4)3Ix
                    zPlelIK{sp`hl&;{+hIGjX9ZnDgl3yk+cz!8F|2_1jJrKYQ!3Rg&jSy&FcX-#HYeAl
                    zD3%jY;aUOYD49y?+Te@9w}ZpMU&vbvSIAX>Chq}ZjhH78MEHJ@9I$kJF>bG|el1bCm9DO>Xy7JdT#fYy$M+
                    zYNFD4TR<+=8o%Npu>>Wd&)g2NT#z&n-0d`Y7}&5!8`!G}(iD8pr@|ns5G+0=H7l!D
                    zwcZ8A^<^AsjnL}|%ci8yLlL9bOshe-7{lJ%+lvBG1>t{4Nb_w$Z6;_ds0ShhnXOj9
                    zc0o4s3kgrINm%k80!#7%C#>fQz8kTocReZ?bz9V^nO<6BsaiUkwb?FVHWU>Bd!Yin
                    zTGm)9_jy{QEng_xz=uqcIZgrFsWl?`A6z(6mpHkyvo_N#^B#T(vlEcDn&9a%%`XSf2nq?BImCu$
                    zDtaoF;O8i*HDpr4xp7i8Gjw8wOC8tRoCk@Qf$^Bz=CMzu+;)}kQ3wgr?2}cBNy;@M
                    zG5}OF6_tj{6!2pvL3u&L3`VXhk)b0K{T#nY
                    zx>bMJV+1cj$KzuRD`34W51h~lW+?ns*B0ihOL}!)Uz}gBURu65zdS!bH@^s<8u7v=
                    z!WC1OUF;u+56I#?0T)0|dNO!6ygz(QkZiG3Ch~rb)JOacoQ7?+UwUD
                    z#%m1z6J+@sV(|I!i@_^WqrJx9dl^25ga4C4em?vckor~4ge3wq-wvPP*Yn|{;qQoq
                    zeE_-P0H%Nlz(0iFGA#{1lK@Bxvy~jye9uax#44^eHp||2m0WOw72<6#Y|cW-0vLZ_
                    z1*rxZquPd#rTPx!B#?RpMAOL+H7Uh7tiW%Ke@KzIrgZ&M=^DiYLp%g&o=8fC;-sXA
                    zlGF<_{8yw4I)a_T4uRohLZj^%1T=jB_|JyFgU_$z&JNWkzX8HP|H1GP%)J^uB6$`-
                    zT}H}(4qH8VoiaC>OEw+a4mQYJE2Muq|LY~?W}AX_y1`Z=lu9{~6Ubenx`+2G1U^xn
                    zFN%58N%cxX2(*qmk39kGgEC8lCH7ZUsz6UbZecO4tUqIc#NCs8cO;<5M`(%R!<6;&
                    z=~ovrq8_zpAr9GGCY!r94}AQUmM>AXXwG0~
                    zrh_B-Nkw!_UAJsA!D9$I7F!drs*E7bNG&AqEr*=&I=F&uWt97&4++CX0`;3h`gE}Xr*P+eFd
                    zm{H(=u)402&7`yh8zRbLu&=KXJ)c(;wN;r5_3DJM{dd`tDc3rPaFO%$;gf`
                    zWhO&e(JvuHLC()7=dI-;g>K3RP&rzSSLV~<{H08mpCJwAti)F=_Y9-Q?ogNu%dBXjTvAo3S!RCG#UvkiIsGnpFh%M5?G4I4fL2G3;+5v3rQ+?Jku
                    z0L~)oKeYExv$V)jN+gexN+xMam`p2Zr9*X2fVB2aT+?NH0B3&)*gTfP?uIm;gA1yGI3`U|yTXdJ(j`W$?viqUF6=t3`w
                    zGGqEv;r>{4nZSQcHo;hTbDkmi{hrsC{v$#-cFG|d%ovODF62Z9^CEQGo}i6Pl(aaU
                    z>fwM(we0+kt2Nq!_u_n>S#;fmVa_U|vK~IT&PUc7o`Ca&u-p!fA+jK?s@6E0wo#M>
                    z6MxCJ%2DwEw@ji~e$5o_bkcf`FzFCF$Z=yidBly!%gBFm1&CoL*m}xI#)lE6j-#
                    z_A^H5{PBO(^Jc>9{M6Q+GP-_Jwz~V%vDIs`Oxme_go21|5i~_`9*NKH-^+gdxhjyE
                    zry1!kQY}AItqz{0+*YU@gyZO?kW5!6Jt|r;1l2}v*K9$ax6p)hPNi9y74NJ
                    zTb$50e^!LDRDdy8gmAIQn@8?^n(l+WV{bY;WvYMlY03ft)aIfndRV@cd$8gb`qR{Y
                    zA)S!AC-Fgl+B~FBZbwe7PXi%s);UQ;PN@t)@dI(1`r9Z#Vg>M9v-uj2GUZG8=rcOJ
                    zLK1wAPb{LRaX&!2;`A!usVU=id8Ww4wx&*T3;D;!LI*!}dr#dloTUFQ&i}7#j(-}q
                    zJVAfvIle7ZY31)lEwj_NhCh*@JV9bAF7I=N2UIa#NS&ZJnoy7C-e~4H?Jfp{bf;=#
                    zeJD*A&MsbAxlR4h2?+Day?r@Rpj4w^r)|7LI&BA?ct~N-nJB=Nk1W;S7iQ#h-Y;bd
                    zJs3V*PA+j(FE3RWFD@)CEiEopFIB6TliPn>>S<_nD^1;alb0FqSi6>*#q%yHpRsu>
                    z>`^x`IyAWMQ2hB$|At*I;olMNSa%ihwx=$lY@a><^RwrEezr6_OYX^A1G|khC%Hj7!G6c@sweVBLQ;?)Y!FxZ7r(`a1oke)Z;>e)HxB+wZU6{D2Gi
                    zmB)9Zya#&cdj|L5P>I%Hu1f{tpiQK^YO`CUo|r|8xxF7Yjcbx!`JP7RMgaJs4A8qt;!fAh`LPf5#U2zpK;emB#>R+9R-vM4*Y(v$sJ#fU4C5%E|P!IN8mVZ
                    zZ~$9zAoP<^-YC5l_L@}qNZkqpu7=A5>6OSn*&mk$)PmfZ>xF>{f&qE;8}|$ftdw{d
                    z;28I#Ut3$t+fa5VpumMY(l&tI>p7!=q)FXyH2O!*dj(puneRDP|0;$SY(blgqH#_u
                    z6$0Oo0i~d$Aj}2#yL>MeW|@CrNR7il5%R4LUBi3IKvCV@&!H7<7j-_irjh}MDsltm
                    zfOm|W!5>ZLS#+_@>k~1ljO=`DUa?^MeNV6WGAp}lpq)_DC#A0
                    zrVa@$9zh{VgN|jA+qA=cC|kx_V2L2~-sgO$oM@S#I&M?T?w2a<&{db{$~iP8UCjF*
                    zU%h?f>aBIisWF!iW$1sxuZ@xMwv6{aytV%B)%B}Jgs_rJFMEFExa&-(_tm
                    zAF+Xx?M|Qr+033uMVC;MNU^}ew@oGzi{K`a(;eNwlsgcF~2oy;JW~>eXYwJ
                    zyPRoMpfTH@$-bpAe)%@KUR!i2T9^eZ7QSAPxs;19!cDl5`={sUaZVtYV;h!b57h`M!t8+XKm0V1D3nWI7gF;w!?L&bkcRnhl
                    zP;yvC%}!$vKv92}-H+UhKXR#`Cztx=*=)3+j%pLmTr=uyuE&MRN?UA?@QyVM(9HB-Lu{5SquzVrY+003MaSP=jK
                    
                    diff --git a/posts/moio-reshenie-zadachi-146/index.html b/posts/moio-reshenie-zadachi-146/index.html
                    index e2ad44b..04de412 100644
                    --- a/posts/moio-reshenie-zadachi-146/index.html
                    +++ b/posts/moio-reshenie-zadachi-146/index.html
                    @@ -1,6 +1,6 @@
                    - Моё решение задачи 146 Моё решение задачи 146
                    1. Моё решение задачи 146

                      Необходимо найти сумму всех натуральных \(n\), что \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будут последовательными простыми числами.

                      Полное условие можно найти тут

                      Хочется отметить, что сложность у задачи 50%, а на текущий момент её решило меньше 4000 человек. Тем не менее, мне она показалось простой. Простейшее решение отработало очень быстро.

                      Для начала, можно отметить, что в лоб проверять условие очень долго. Проверять на простоту числа порядка \(10^{15}\) достаточно сложно, поэтому их нужно как-то отсеять.

                      Самое простое — не рассматривать те \(n\), что хотя бы одно из \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будет заведомо делиться на какое-то маленькое простое число. Это даёт достаточно хорошие результаты: из 150 миллионов чисел, после отсеивания по простым числам \(< 3000\) (этот параметр я подбирал уже после решения задач: если он слишком маленький, то будет слишком много проверок на простоту, если же слишком большой, то мы делаем слишком много работы, чтобы отсеять несколько чисел), останется меньше \(2000\) чисел. Их уже можно проверить непосредственно.

                      Тогда алгоритм может быть таким:

                      1. Находим простые числа меньше \(3000\).
                      2. Для каждого из них находим допустимые остатки.
                      3. Для каждого из чисел от \(1\) до \(n\) проверяем, что остатки по всем простым хорошие.
                      4. Непосредственно проверяем условие. Важно не забыть проверить непростоту оставшихся нечётных чисел из диапазона \(n^2 + 1 \ldots n^2 + 27\) там могут быть (и будут!) другие простые числа.

                      Непосредственно сам поиск такой клики можно реализовать тривиально. Ниже мой код на C++11 с использованием библиотек Flint и primesieve. Распараллеливание хоть и просится, но смысла не имеет, т.к. я получил ответ менее, чем за 5 секунд.

                      /*
                      +        
                      1. Моё решение задачи 146

                        Необходимо найти сумму всех натуральных \(n\), что \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будут последовательными простыми числами.

                        Полное условие можно найти тут

                        Хочется отметить, что сложность у задачи 50%, а на текущий момент её решило меньше 4000 человек. Тем не менее, мне она показалось простой. Простейшее решение отработало очень быстро.

                        Для начала, можно отметить, что в лоб проверять условие очень долго. Проверять на простоту числа порядка \(10^{15}\) достаточно сложно, поэтому их нужно как-то отсеять.

                        Самое простое — не рассматривать те \(n\), что хотя бы одно из \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будет заведомо делиться на какое-то маленькое простое число. Это даёт достаточно хорошие результаты: из 150 миллионов чисел, после отсеивания по простым числам \(< 3000\) (этот параметр я подбирал уже после решения задач: если он слишком маленький, то будет слишком много проверок на простоту, если же слишком большой, то мы делаем слишком много работы, чтобы отсеять несколько чисел), останется меньше \(2000\) чисел. Их уже можно проверить непосредственно.

                        Тогда алгоритм может быть таким:

                        1. Находим простые числа меньше \(3000\).
                        2. Для каждого из них находим допустимые остатки.
                        3. Для каждого из чисел от \(1\) до \(n\) проверяем, что остатки по всем простым хорошие.
                        4. Непосредственно проверяем условие. Важно не забыть проверить непростоту оставшихся нечётных чисел из диапазона \(n^2 + 1 \ldots n^2 + 27\) там могут быть (и будут!) другие простые числа.

                        Непосредственно сам поиск такой клики можно реализовать тривиально. Ниже мой код на C++11 с использованием библиотек Flint и primesieve. Распараллеливание хоть и просится, но смысла не имеет, т.к. я получил ответ менее, чем за 5 секунд.

                        /*
                          * Problem 146 on Project Euler
                          * Aleksey Lobanov (c) 2016
                          */
                        diff --git a/posts/moio-reshenie-zadachi-146/index.html.gz b/posts/moio-reshenie-zadachi-146/index.html.gz
                        index 8b6eb1514b00e75534cf479c10b53b7ac80a2e97..659ef1472faccf83daa5d63dbbc167d47c2d6323 100644
                        GIT binary patch
                        delta 5038
                        zcmV;f6H)BND$FX7V}IA6wMEW6@2@kWIpuTjet2c|_qVQ+rq?p7bLDgS{2Hqh(<9ff
                        zlFRE=BL0NY6_1Wkw5D~hTX;6JZP
                        zTeP6NZo%SCOEcN$RE4W369S2V$)F0|r9z<&EVyce^M*+^o4KmaTZrWCy4GUmPUTjU
                        zncU@elRD?!b`6bUf~KvUzT+^{WO_z$mFaSoA>NKnD}Nb}-t!PsW;zD0ai`r1NKZ?2
                        zG`SDmZOt@JTBwg|ZOdyf+~5{JX;QaV7w%}5o1V;=&W7~!+BS6|#?%(GVtsB*TrDkx
                        zpGyr~GkGIIJQZw%dChh$Ib0OfHYnRXaI8K{HKN^LR_W*D@8UQbn_E
                        z@KFu3L4N_q7Q~ofMKe9>SegfUN~DvD()qUYqI1;wfm~dCi>$zGat#nGq%Z*^j_W4z
                        z0Yl@nar@4l7%pUrBd(+OD)6pb*n*tSokEKnfR=skY{K5%>3nog!L^`=%)N~
                        zjT<`=8vP}*HwoH7MUg4J?m#|Os=w!LqB)ebU4LdZh-Lw&p2Mw1mA5?uWHf-hyg_OX
                        z-*%~^l3NfgE+u8HSFLiq35wehaimn+cEiyON_KeL3Bbz*txC8v0KL7v?FXU^!Y-4A
                        zw;gIQhw5I%bK1bOrh9A)cq8wL`Q(b2ORnK$f!^bUwQPrP`K0MRn>vhII#tUBJF2lr
                        zJ%8=qHP{wm1{4+tWT6gtwWzby5qDi?(3<8bfjaRz?>04qZwJxSY&g7a`?Ecom(bDZ
                        z(7J=dhk9ZQY~Ea~mRUf7L8;5zz&5mSfQvA9C_aLeI$L4o9I
                        z+XOK>2L$T&SI76EPQN&Q1ZDdO%66z4z<($N@UJXwD}uXi3gmDzkCEl})mlH~s-bzM
                        zvn$okzXHp9ou@!-@AxtDTZTX!3)t2g)GgRj1XsoG2=GDcfpWZr<^#CzJU_mF{BQ!a
                        zS`9os!1<@n6M{^FW{$9_Nrg|Q68zasYE_Yx@ZKP*a-nSo3Ku#q*E#n>F9YK-tAEY|
                        zpNhEcExt`5BuH(C+@hGIEY(K?lgb5&r7AN8e3~;<3C4XZVo$Q~F?~}z60T)0|dfa(({N?c@f@qVuDj@A4
                        zT=)4K@C{{}GoE*_qFRjRKi3RRZ?Zfz$pyc>)HvU4Y0f5Qfl_sJhkf3vx%M(30E3r$
                        z6G1Ptfjh(xyAWGY>w1*zx7foBV^=%h0b56)uW#VzGhpwqb3`!8J3m1f9e)tWGhf5K
                        z!{e_B1lCs|$2VdawEQ)Q>+FHl~R%oUAY1aC59%>K_RCDC`0Y+xRygw{1
                        zlp=EzCtVn4(&cd`y*19HQj{L(BXQzlmnH#qe%*Nn3c63qv{miA#C#12bRRT)1W6RM
                        z2cLb-fp!nd1(@b%L(J^*u7C6m^b!HRhxcR&M8o|VP`&VzKal!L)Rd>v!N7=}zv5Wb
                        zlsz>Y`)5BVQ>-egMLoO$>&R9G+)=3t3*VQC&nNlcz}*9If&0MYV=O}Vfzm!Ahg*+A
                        z1N*!P281+^2)a+i>&eC9YoN|O!5$IXcn;M53Aq1Ba({@?0{R2=VSoG_AX?%NJ;Hz@
                        zZxo9~f;{=s10I!hzK7q3h7B_;26@k7YbP5P*BR9^)lxxbu_<
                        zfu95w6eNd?_t@8UuS_$9oDkuDFFHQ}3%+DMfWBI~8bB8yUH=m*!`Xlb6c-;0rQ#pH
                        zC|%r*1jDnSTM;N92+5)@l9PDCJZME!Us0#f*_Oclbjgc;Eu
                        zdFjN5!sUf)%KQCh3tbQW^?xJ~W{_`@Xsla(BRan$kt}4Oc76mtA=S#6#}AjJfl3#P
                        z$N;7kU{s_82!?M3nU%he
                        zLcIhgzZ71KS@uiflL29$0Af*ZiHM8+D0|U_gb-n-UBdi{a}Gq-lVNuNQ&HWA{T6`a
                        znadpr(EZMVA=_Q)ztu$VFH{w)^ot!IUJj`B9hrAqFCpbfP_x%agh2X5Qn6
                        zL1_8`8BG!*^x^WkB!|Bv#-7i0my=)!P%b483j%2V_PUKs__=<#S(E|mlc
                        zzr^ZPyA67jvK$r?=){)e@0*>-5P$F+2BP~7aIio9R-U8#3cOQ{xK
                        z4@Ts#xuIyHkmPmTqQj*Vfu$3Hb$HK?-4tk7OuFgP9r6LMX%^oiS$$sYYD|u@FfM2+
                        z)V5N6g;~1UHfRv3eG}?R6zOS7Rx6L;-e36OOF@CQmT*;;`jx2mnSjt
                        z)cn-3QJ9vaR2)O$u5oV0GX#ca?uM{(0#n(z`-l|exb((`mn5jwZY5xxj|G8&FUFK#
                        z?#lP+6{32hu3`DPcP~--Fg~U3V`(R&Re$5|qgztX=QfSnhpTmB5x{R*J;^B936z;A
                        zHTyi#&Ema+E7fzA*pU`fs-+~R=ToR6P8|;Q+Kv@3c@0H3T{>$=IyEcMdv+S9Lq!);
                        zh4OetOUCu`sXu8U7Yo?5BMCDmD-TW%sgxeAFx$z`899)F($
                        zklm(sz~9enEqgg3-aNjc8OEskfg*3{3@+#&nVNTc6+^~R0{=v|BbZTu19JVABA?Q
                        z-uBoQoiv_ab>lvtD+L~l}kGk-_CrsfguHK{|ub~Wm_1fQSuH&z*8F0r`hb2LSJ
                        zdD`g=ND8SiKHU>2n5naqCp*XF0>Y94r!rCYSxegnt)~lIM720VvE$1a@qihKISOc|
                        zt$jXqlenHt3DBHC@Yxlz;f&6Kud(=PM>RvX8WmN@O^@wX=Nq?$zebnfik{BLN<-rY?e
                        zT(RTdJ*BJ3Q?5IIQLFO)nlxr}7*)ZzT}dvn!?=(d;&N(;w^Bot(zCUg#Mkag)}v&H
                        z8e?1O#>yufH`5tkD922blV=6Q#bRoZVsU0LQ!dA**72>|*Kb@+ujdQXi}Nd4O^feO
                        zH+uI0X883}_dD7I-j9_Da~QMs^?
                        zklVUUoWu^rNZTjvP%z7-j+Zj|50Pb->G_usR5i_|8>bjqr<6=ltTX-6F3z^&>3XJ~
                        z9MQvo7GIkrF`R4wO!x)LZ&~;hvhZ1j@kX*tOVeewNmMe6J=OG;XUL}M5P!E@7^R-H
                        z4?c~RF$QC7bdZr*nP#TF11uk1`s-;O##q*x78pTAt;qaCjXMX@6;hS;i?W4M)-%
                        z=4xYX@lN#IT6#C_7vsd-^%wlq*?3L%+JqWhpK*(NM%+&I_cm)7pusl*BJ%9Y44%hI#
                        zk5QmdD$NskY-W1R+@@~Z^k7lFG^KKe`2ATZXZRDcGuiAJ<>3YKs-c3xwyJY;;-yi4
                        z3SMWl6uwOB(&bARE?ii=Tnyi+CEs4;zfoSktzH~Na97*X1gbk|Ji5B5g(Pqwu0Vz#-9#D9iGt!^o7l5fH$C0f8)VL#d^T6Ff+nT)ybY`sCm>^
                        zb~Ym?WacG;9w?O=064-Fad2pHgzU3<>|EE;acc0sUfrL{?VftqeOu>Noi!?}^ppI`jek4&8#g}Kcz^ZA2i$>Aadg+R
                        z+n{&8t#X?>8d`%{7IhE?Z6e%NnO`TB&@4(o?frI5y&}kEzfj0RcLM&9d@PZ*%nhWD
                        z_<+64dTwAQu)0LPAV7y&F5{MqK)|~=_W?k1c;W7}YTR_?wZ*SG4tK(Te;^Xi6%sK({#lra_bpc;}6`90&ZKx)5r`#BJ}_rD
                        zhNn#E0g0l@^H^{=qxvzk@vamjM}j*M)O-!!t9u<7t+c
                        ziGOwDp6nU=KLixhA*2@~nRP+Q5s^~?{aeM?NO;^pCJt}EB6jDOdv9Rb$Urb^(1&Em
                        zxe6q-;0g*!bm~ARxlJ3)g|emI@ifP4+wXI}nGLl}P#w3aX6$5g^|mEnfS--QDez+6
                        z|9Iv0^_82ekW&LHABxb0PitM{t*h5Qynng+?#k+l>H{ptV)O^s0>@uh<$*+P%Wbkc
                        zl#jr`p|~UPKsGZ*V#$kHqfjwV!?U7BBJ<~sLYIdS&SUar-V`{|Hzu(6osZv}si{>!
                        z_?wAO$HdC6A{&fs*kj?bN92!xBr)x+`_9g)*0`y)Xf}iAU1a9hitF<#p5tQ~SAUw!
                        zG_pO73N&WBbG;`l4IZ4~AB~Z8povpR7}4-(pq>LY@F2Spr)m6$f3`#LUgpP3{pX12
                        z&|o&WvlE=YkeA0V$Rlj}UK{Eky)ca6_k!5L02xnfj7K3C2dVqBb=-eSm?Pd2=g+(L
                        z!S$P~{>&tfVHh=<#tr}?52)!o%YUZtARZnb#3R;X-2u5Y8?n}!lWT$vTl);Mh4=;D
                        zxwejei&rW>Qj>+I&C&GDThQ-(41GaneZGI3T3XGdA24fk6=yQ5;ZMp287muInYAP5
                        zaIkH*sYcH=^MfXe-ld+vOP!A#XtGFqAtT}JrtK3N0Jy_EdfkA@nNm0fX>S{qAoy~m
                        zQ8AL1JvrjSV0?H6b09z^-i8`ER4=-&ff3E!v2=0#7hXXUp-y;(XR3v=K%cuzT-Aof
                        zjpf~hwYVxDmwkuUxkIy!oGYZ*ozKGWF!0AYrcIo$7k40=JcX@X5C@h1A5X;{%D8j@
                        E0AdT+lmGw#
                        
                        delta 5076
                        zcmV;_6D#b@D#a?0V}Dm8u|#s7_tzQHobtJMKfJQ~`&(B@(`%X4x$?PuevQ?M>5=PK
                        z$>sGb5kF_b;V4F3pt-5~hz8O9Rx3L0#Qpw#T>?VL*u=
                        zyv69Y%^fc?a(|l{UbAA*EvD1FIEcUsc#~P1#Gz(IalIXrx=l&}LDQl2ilV9o_~$ig
                        zixza(Em+)XX(s!es&Eu#LLd<^8C2m?p-=}7T(!Y@!=#$cTvg{S#PN1rYcX@Da;wQq
                        z?sB_Ho%3$HhBh%l(N<31ahPc`JtLUPbeYN!Z^x#UjDJV(d59@975!`6X}1E()6yJG
                        z?n8H5GmR6L>7!cP^4beGxW!MH(yi5nJDTODr!uCaA^p6zO0a=vt3IL6~$M!$u?&JX0`;#*_|Mw4rRSRsW87;#)Ti4V9m
                        zJ{!01+=<~rrZ?g`danZSx`i#s=iDi@xB+O{=T3f6y`(M*cfhP)E=XA4GKFrsFW0!S
                        z6QR*x9(xm@9aIyU&g%~3QlOWTUzZkqx*oXlfnxqWrk54mb+Ug_*g
                        zwezpQ@?PgD5ZgO`jQo}%5XSdE&~~64FQM@O?mN$q?;k&$0IgO7
                        zPY-bZsq=&&lc1R+Y-m#9lc@xMcavIGBqcmIh^ky@n}NcGj>~n4pD#~K9bSYmd<`+w=
                        zrOQii6qky{h2jPHtq{9i!*R*jMSmCj=i~ciu|&WH(32i_o*aL9{D>ghWUdNGdkEKk
                        z{sw$QndXe=9jvGpqxsJ@L(`iq4-Im`FE2IDH(Q#siCLgj9o=1@w`#7v3<$vBrQSr)
                        z%WU8d@t0kQEvR)pO7`39VTQ4*o$r9HBhc43@cS9Cci1^180DRxAdC(O$get!-SE%7fs!hj-g
                        z6pKZIJo(ZC9+h;yhtEUAz3-2P|NA-oE>0Z@s%VwYbKnX2dLcM{6fpr@{7J>c5*+V?
                        z8Zn0V2f`WjAVT4Z(8!+TQfLbKlvV_ncqnuM=(;xiH*kW-GM*j?z`b0L@sc#$c}j%9
                        zPl5^xl0(LO?CZMM8Gk}fh;Y9bogaV&U$P!RUoBk?pbL<${|S}hXut!Ci;sm;@ef~=
                        zF78Hx;aSkF2$T1Y7=@MuwxbhVY-4g~mkRgexyN{jJn0X9SCVv(i4EKjbq))-^LFdQ+
                        zH#rV{Q%3evKf8(g@k|7y@L8EEgl7peqCN7`i4TR#3)htA`^^@*9{TJ5NFdB0-y+di
                        zxB5nOen%o%$UyD<2z)}Sl_QTIE=dEGE*6miOew&qNC^-O0Y%{6_eznrN#JnORWR;R
                        zsF%o3PtGRMWPcs6$MdGQOfEp$>Z&p;eIJE-2~2(|yco0Wm&7Ln!af1SqTUh_7yD86
                        zq6rBh!c4n_`4h(+h^!~W?f{0Ox)1v;0LeE;q?WtJ9Rxv5{Sb;SGYF>A`23NJuz+m$
                        z<9mWBNo4b*F8M3zGy2IDZrYhCK88JzNs;y{E|;itsMmI^
                        zc*$!hy6MtcJJP9Hf!?#zI2|gwm@1UVGg>mPUzgEFki};)W?6v%ZuiXU1b1D0`0>fCY@@yS_897-Y?;xJR2!h
                        zt?lul!X-;+0(7E$OG!o=ODmJ6g0zVgGggB2CTWk7eHsY8J`!Spw}m7nPT*H*ReMI6
                        zHnrR9C8b&@_)Bi2)pk8nqxj^rOZB$Lw&YIN#;x#poaIZ-n
                        z0=BDB$0hj4q`#KR2y=!D
                        zHfTLv;3BHU5sDpO#)t>ZK+I7_HvPmNicv$Nq+&C#1F
                        zi_k=ttkDLu5>1(#$kl%mry`b-o)SCtk~dC9OcK#dUixi6
                        zUNRZ6SUQHT=6?z9F&vPb(yH?ir)zL-Y&aBq0E0U2$mND#!)#$#kG(WS^v$Fhit{Fy
                        zdZ(Ic#+3!g$3KC3X^NS0}7x~w*dN@lU9n!fT3Su`Eub_;)_)RXqXr?E1|V2q6pGBPXE
                        z%(Qoa>7z@3J*~rdlcHJQ$~pNZhZL%xO!NtF3Qq1eJO#)Y8M2(8ad#1!H
                        zp9ESf;fsH~F5oX!CF}THkSGR(Swt*OqM9r#5-9Qk+frHgNr
                        zig=||%uPus@+1^Y1^^+xNX(iJX<>@>&mrzQ{0ag%k*74
                        zJJqGT;SWQL`~BETqf2G?iYqMi}AQ$6`M{;YG1$e38PkxviJ#L43-{>15bR(}IDEDCE5
                        z)i!5HW6}xCiNH_%cwC~rPBba@OuEKP;Q-eW1*XcX?A;Qlx
                        z)}nv!2R-?yn;9&+KW}@(TB^jh$_-ut02nNfR7lSs|EI$>eC=ZtD3nU`1Rk52UNg6;
                        z+crIzR4+}boFRUH7Rnj^gzQWfdq#P9LA+h4V6d&~+?;q%)SrSk7%heG&$@K^(uE5b
                        z7B3gWmuSfs7WprcmoKOndk@^zwlsMbGc$k5o-?@KZc)oq8`QgMQvCYP&UGW3!S`d`
                        z)$Yl`8@7CJ^u{Z%{qB`lfA>meex7_GUh=!8IYcvA!-Bw2bbzLgk_%t|i>;)H8Kp>D
                        zk@G0LXbpx3*1m@sba$pQYM!#y*W?bCW=YxoPc|O6oAQb%dy-gfM#(1ngQ5wtOVbk3$@atK)@7g8W3t8^_88?$N`yoiJ%8cWd;C_
                        zFhv|3S{xz!Y#uw-b#xpWyrNe(th=tNo4jq*P0f*S*VkZp!DKbuHA27^7S+pYv2X*9
                        z{!Y86-gV#Bxm9P4$}0UNzjEVF{>Fce4>sOkz3~Be;9DHswd^+Noo}n$rjCZzV3tK4
                        zgh87KcU9)sNhLIk5>R`;T~n_Ja@j8wvd|rXza$?^WG!<8sUtpMFSDK-7zwN{kuM0)
                        zp_a?ITJ7%9KXBek(2~Ji+thYeFtk7fWx___!vIoc1x*x_!IZwJgQ
                        z5e%upF)&|qwFbR|+ll~2xz&G83@%?>)cL?QnG7&gks2rm)blC)WI=rVoX@NiFkdX3
                        zFH#rq)mH%uej!LKgza!0n7-=jnoZp#x#UQSdlP|J!sG*Ec4K(TgdUJ6s@#GFFK1Lg
                        zW;WiHV&q70hNvyxbHsX%EJUw!lcV1?JjL;r_>VmgHM
                        zLL{>;C^;f>DxiO>_!*9%+qjlsFBG0aih@XA%ydoe3>@|PV|il?0x6s_hxEp6%hVr;?ps)va84jBOCTu
                        zxYH5&;~z;(d+WZlv#K?2YAu@0;1(B|`L*Kuyoy`*SjLqmGmU?2Pon~j+3sBLrb>f*
                        zW%#>cB<*416cVmzxEoN<9vZlB-G~h|{=?tSA$S$@|lV5r!~f-kc)%V{n0wEKP8M2Z;A8AUHjnr%~gM7631{EHJZi_
                        z03!FK>D#`hZ|{E{9`3y(=3?Coa%whWt~Dp;1RJ*Y8DtCb0p7W`j(&?rDn3$^g{IBX
                        z^vzq)?|ck>L1ulv|2nm_nn^!k*5)dXWLCo;lnpXgHaatFN4DNz+iX*fZe`{NO%%OL
                        zJ%N`xA34xuk@iAH!r4vRCo}+Xhk5k60fRH8a0t>iDnV@UswQ@o1OZtB*)(x_!bN~Rf&esM2
                        
                        diff --git a/posts/moio-reshenie-zadachi-60/index.html b/posts/moio-reshenie-zadachi-60/index.html
                        index a733299..19ec76e 100644
                        --- a/posts/moio-reshenie-zadachi-60/index.html
                        +++ b/posts/moio-reshenie-zadachi-60/index.html
                        @@ -1,6 +1,6 @@
                        - Моё решение задачи 60 Моё решение задачи 60
                        1. Моё решение задачи 60

                          Необходимо найти множество из пяти простых чисел с минимальной суммой такое, что после “склеивания” в любом порядке любых двух чисел из него тоже будет простое число. Здесь под процедурой “склеивания” чисел \(a\) и \(b\) подразумевается получения из \(a = \overline{a_1 a_2 \ldots a_n}\) и \(b = \overline{b_1 b_2 \ldots b_m}\) некоторого \(c\) так, что \(c = \overline{a_1 a_2 \ldots a_n b_1 b_2 \ldots b_m}\).

                          Полное условие можно найти тут

                          Для начала, можно понять, что непосредственный перебор “в лоб” слишком медленный и нужного результата не даст. Поэтому хочется уйти от, как мне кажется, не самого формализуемого условия к чему-то более простого, с чем проще работать. Давайте сначала поймём, какие вообще числа могут быть в одном множестве. Для этого достаточно перебрать все разбиения на два подчисла всех простых чисел. Это достаточно быстро, порядка \(O\left( N \right)\) операций. Важно не забыть, что мы можем разбивать число \(p\) только на \(\overline{p_1 p_2}\), между числами не может быть нулей! То есть если число 37 разбивается на 3 и 7, то 307 нет.

                          Пусть мы получили набор таких разбиений, то есть набор пар вида \(\left( p, q \right)\). Давайте составим из них граф, где вершинки это простые числа, а ориентированное ребро из \(p\) в \(q\) означает, что есть пара \(\left( p, q \right)\). Из того, что порядок склеивания чисел произвольный сразу следует, что рассматриваемый граф должен быть неориентированным. Таким образом, все пары \(\left( p, q \right)\) для которых нет пары \(\left( q, p \right)\) необходимо выкинуть, а из оставшихся построить граф.

                          Теперь задача стало гораздо понятнее: достаточно выбрать клику размера 5, что сумма значений её вершин минимальна. В общем случае, это достаточно ресурсоёмкая(как мне кажется) задача, но в реальном графе количество рёбер не слишком большое. В худшем случае, по теореме Турана, количество рёбер в графе лишь с одной такой кликой примерно на 10% меньше числа рёбер в полном графе.

                          Непосредственно сам поиск такой клики можно реализовать тривиально. Ниже мой код на C++11 с использованием библиотеки Boost Graph Library (BGL).

                          #include <iostream>
                          +        
                          1. Моё решение задачи 60

                            Необходимо найти множество из пяти простых чисел с минимальной суммой такое, что после “склеивания” в любом порядке любых двух чисел из него тоже будет простое число. Здесь под процедурой “склеивания” чисел \(a\) и \(b\) подразумевается получения из \(a = \overline{a_1 a_2 \ldots a_n}\) и \(b = \overline{b_1 b_2 \ldots b_m}\) некоторого \(c\) так, что \(c = \overline{a_1 a_2 \ldots a_n b_1 b_2 \ldots b_m}\).

                            Полное условие можно найти тут

                            Для начала, можно понять, что непосредственный перебор “в лоб” слишком медленный и нужного результата не даст. Поэтому хочется уйти от, как мне кажется, не самого формализуемого условия к чему-то более простого, с чем проще работать. Давайте сначала поймём, какие вообще числа могут быть в одном множестве. Для этого достаточно перебрать все разбиения на два подчисла всех простых чисел. Это достаточно быстро, порядка \(O\left( N \right)\) операций. Важно не забыть, что мы можем разбивать число \(p\) только на \(\overline{p_1 p_2}\), между числами не может быть нулей! То есть если число 37 разбивается на 3 и 7, то 307 нет.

                            Пусть мы получили набор таких разбиений, то есть набор пар вида \(\left( p, q \right)\). Давайте составим из них граф, где вершинки это простые числа, а ориентированное ребро из \(p\) в \(q\) означает, что есть пара \(\left( p, q \right)\). Из того, что порядок склеивания чисел произвольный сразу следует, что рассматриваемый граф должен быть неориентированным. Таким образом, все пары \(\left( p, q \right)\) для которых нет пары \(\left( q, p \right)\) необходимо выкинуть, а из оставшихся построить граф.

                            Теперь задача стало гораздо понятнее: достаточно выбрать клику размера 5, что сумма значений её вершин минимальна. В общем случае, это достаточно ресурсоёмкая(как мне кажется) задача, но в реальном графе количество рёбер не слишком большое. В худшем случае, по теореме Турана, количество рёбер в графе лишь с одной такой кликой примерно на 10% меньше числа рёбер в полном графе.

                            Непосредственно сам поиск такой клики можно реализовать тривиально. Ниже мой код на C++11 с использованием библиотеки Boost Graph Library (BGL).

                            #include <iostream>
                             #include <algorithm>
                             #include <vector>
                             #include <set>
                            diff --git a/posts/moio-reshenie-zadachi-60/index.html.gz b/posts/moio-reshenie-zadachi-60/index.html.gz
                            index 94ef1f7a943b909912e71f910b53a4cc323a756a..b3ed2f8ad72f54c0f8602826f8e4d67406ffc8e9 100644
                            GIT binary patch
                            delta 6570
                            zcmV;b8CB+sHjy^4q5*%}ONBxWNU-yD!>DUiF`1pO8cjsbv^kf9QV_2=GH}s@~jvnpNur;n
                            z7{@c@U=TFDgd!t)&4PHED*e`I5yhgUWi!1_6dfq#mZ8^6MvJS!qYA^z8>C_x+cvfG
                            zC*BQN2p@D+RM(Vtwhf
                            zcUNUwgsG5NEZ~J&VAUecQcK*mnMx~)mGZ=i*EzePsK&PEJ&n3$v`n`*r#T7T?;T37
                            zQP|LcZ-IZ#8;hkC=8eE0)#XeepJ`|gtVH?^4lDvX1KTrws_tUPZZOga^0wgzD
                            z8nEH)5lGt)JC7huzwCSkS^EgGc2_ijQ83_M>B?3g?v^Hy!_6FemVGSOx-M7hs#h9&
                            zs^t79klc2j!eH&rW2AQl9C0jQQ>jzCU`iJ3JQjaPfDbAUDo?)3A9CYbQt-gEnbsy$%|)`EV8G
                            zBL;uP;;afj=$fhkhN{fk@v)0;!3sRO{YBSd{}_VetT{La-bfLQQ242sTAW{aBR78~
                            zw{T@`;mXo4=9lK@=jLCB-zj3YD%dX=yC`J;-g!h8t`O%hoo~=52qFxor+}k|(0k0%
                            zfMQ6{1~YON=2D%}+$V~vR2wXJdA{K0m5P61Y%~>X1Koe2G`g~WO|RJI^5uC@^uk~O
                            z7$ns*1OH|ldEUV!_6XC8>S@*~iX
                            zk>)A3?m5rVV;{>7!gaB+^JV7`1X=1l1e`BP=OIGx37!x7V$=(0>3j~i4&(*KuYG^?
                            z{wzSF&jL=w2$5!&y!OhQi;MHiaJ7%ufa)o92b7)1qG@57I8O=S{>FI%I1VK2XPw8u
                            z%sz@*v_i6Sl^^dcW0Hm8OY$!P{OG1+ojUiMGym{x1Hxg
                            z(7R$p;09=YESp~fd0$9_#9Jr^|B*?N+=UcuL7JeSD&+;Dlo!ceO*Oa;AN2=gP&R;~
                            z0w^jy6qRzb9|dXxY{8A(M?x#UNUJ>{X+T}$@$U{agz`bc=#upYdduHYbZ&p91qlj6
                            z0O1O!J`l!pIOsnE1rknH+yqE5h39q3@dnJPYL!mMc(HA>k_526LD0~P5514{Tuw4`UkhP#L$033pi31WYw4IhD5&{tQzf#D)lpt>i^cjkJAd0vB
                            zefopD8m;kJa*N!xSiOJ2GktO7$Yrbzv3SpU0Ym>u*p2I*ZVGnA+4Gx&&X=BZp_=<-
                            z@YIz~FaG-zWe&upBa!s>-H_l9(ThqZgdnrL*o!+^>2g0}GU+o3%&IOIF0BK$f&Pdl
                            z{NfUEzQ>`3Szybqbm)F2UcYjT%U+s5ieE<$zmgTakk{w0$ZCHD#|A&{MMZQgIfRg4
                            zFTw1I@kBh7p~lVjduSQQEX;Y~j?*K!2M0LY_y=R{vp`WwgD|sXbI2zA{L-5}A<~0x
                            zEr7Iv!=dr~9yIU+CV3nf>`>^rDyE}ehZLoA|jDs4+EOWXfpS^8N~Cv
                            zqmT^TXHnqxzFmJd2Q2@2H{R@G{Pb+QD^wxLm?HcOP}vs{`^q)xtVbA8eF~j{noCah
                            zfMF5xL|G`3iAYzXW|5gk6j1|A2&FuP#slGwpLr&WW{26x)tZPffB?Ptu-`MV)(z4K
                            zU^vL5$H;(uKtwQ>HhLstwG50>eqiR2<%eX6WZtcCWL=l7J}n0Mn$&>8YtGDNZ*1RN1`D36VzEas}b|i<7}dW(6Oa|V7&yR
                            zelMml=p60rXd0dlP%KEneEG0fsr1eDUUZc!FMfX#UMbbUnPsDIXLRU!6H3R1Q}B#+3-JCAnQ15KuG>Dyh>|~}&
                            zuQ0u;wN&bbrDGjxsnTm2UuHnBMV01jb-o;g$-6KA%!HB?odQLx8y4e@QzT&vrhtZZ
                            zdgI%apWfh2#XP;it2S4eo(T8TA+UlDU8sMfLl+eFo>HZHb*GF=x%q~9T7uhb8GPBa
                            zSd-d}Zc#yrxOb8=+(?zg2A40L(1>RX;8xY25j|A`)%(#4H%~2^kL|rx-)2h3G8AHcEhfFo9EAP^MTm
                            zji|ophEkz*rU#9Z$tE@q)z!dJGLv||MS088rx$JFD)l_2*QnWbEhG`%3QS(JLF5~H
                            zw^WOroPtOkJ2hdO(lmqcsloX@GfDDYi*C8Ta_mn`6NTY134~cywPlr?EscLiC37Kh
                            zGQo&yT_Yjm+MUwkMv(LwkDPZxEF>r>TH(=mIXZQh5+yGzXa{=H+*|-U#*=WM@cL+&
                            znqpAP&qt9N2r)GN2v3-_3Oa^eTyfF
                            z1@CztoZIq~~G<;(XfMbe2HE%9+08KYl?IvZ^()
                            zL5}NQVP15y^&$uFWS`J-;7o-@6L451yc~H9)JBq}AF>))`UMe@ONi0XB63o!dNZZhR3Kh8SsA*Z5sT(fjYaf(;$Kzwm)2)b0gLBA0SU@A
                            zhEpp%qD)yrA`M-_4cv45G_uv6=Kf++*`Vd1SzDaIk&SHVk@I_k>sc3TVQ_yTRVoyS
                            zMVrPJwTYr>WY)}XW(a?8DBS(Xbb{}Fu}P%`w>GmT+_H&o@R;YE&duT*PBXU*rUn)%
                            zRJ*3AH&8ZHDhmG@)>uX?aM2L)O|+TURLrOXMujt-U;agzM=DrdxH!vCxRqc>nvlCL
                            z>prk=!-tm6ZDQ1jNq$Z?6RdNmx~->yF$eIy6eO%rTbasvpJ9KC7$Rze?nItRnvsi3
                            z%Z|Pi7IhSxf>Ei{*f)zYK^oy336|kK1tw63$Dui_3?Fs8ZIVhejMh7mg|!}W*LR$y
                            z$hgKvwccs1voE0O$|uQ#a2I<+3G5ABq|u8sdREeCl2I%;j4l3?ESQ){9jzW>!!7F3
                            zGrd_i&c-dOs5^gz-e-1CgXcM)%}>KCPHPPaU42_I6FU{2jTNsij#f?ZWYWnT@sV4H
                            zAL(rKR;zijRCM;1icZW7E(*%id=880Hnn&{Ie(lQGx0~T&M42J6>slwdiVX47aKMI
                            z)Q6Tw?VI2^8cNkw8r3fQpR|sYIqFeMuE1xyVW6d@z*K*2aeBY(eS1MbR2J_Jh>~T)
                            zb{E7hl*t<-`8%nsn5f{Qq*i<`!=@4UZALurHr5u>$w?s0V3R&~js%s*IW~Wy%ZTU5
                            zBqx!5*=X^^>)a8i()(+;@mJu0&@zp&0dDiC240`W^OUg-afx~e-S-hb>8@Z@<4Sr#l`B>~S``@btZ0Z_vJvaT
                            zWX}sveZFqdt@2jXNqcy~lsWl*iWpn>aqTtcgA#Fv3)|q&2A}8+(P}2*F3gmOpW5k!
                            z7if5BqShA1wjGRp;_WVQSgb_B&IXSX}1L0J23?8CodW%l!T_Ld-I_nYZ
                            z*sX~DL&JIWCx^31F3Lq&e2SD6PUNjAC$kw4z9Nj@`x)uAU*YIrj#iC)93H=MIPj!Z
                            z&3@8X+=olN;KSZJUad#^fHHW{_+p=qJ}OlRu&lofRoPC>U
                            z{bJNQElZ0@Xe%SL
                            z9{q7&>nuGEe-`#YN2+sTgBj`IcOq^{#X2Mx-Bz}yaD?!@n^)xLx<*zQ6CXEJ1^zhi
                            zp$@aj#I~gqefTST?$`-`t}F7P%4xk&9nBQQ$Eq>v?_+=yr?usa=OQNh`Uii*P|v~9
                            z_N_Qa+kNbGswdpHVx4fGfXajqx^I=I_bo+JJDM~0R~v0bJg$z%2i`c5?=U&3zz}6a
                            zH};93uz-^J|L`8Ip)boAe_bUQY{Cd%wu6_u&ixmO%qRLqB5~|G){5^L`udN_*V^9&
                            z=@1Bh_O&yD&%#h8C|AKME^_U&OKja?kqjQTCVQ+uz|6lTCwi#i1kbF(`U
                            z{bD_l*PV5Fh&IPLnRDEM0-pR8X`}6PF8HZUEg=I4l4kB~Id!NoM=c
                            zxAq@Vft;1^Sr|0;u`6D7wvJ-Nc#;O^r$N)Nn7X4)lkZIZImYA*nGb)d-O~8vr#YKU
                            zFH?;+sUCU48&l%(PCUidZ{$a8F@diKu9TjGc^2m9sIlRk@KqT(vxxMLFD1$M1c!N9
                            zCCO#I2bloL<$~5w#v%QrkKBYSCyB|!$V^o*EecmE+bYe>%&eFt=Wm@y&QoW%^Jodk
                            z;g+G-ON*E1Uw<7ycnq5A@th2-3OJhGk^ej0Q!FjhIELmsSaI
                            z^qO9=&1K-CEji9h8O!BD!gowsOmTXj7w#!rioA=J1DU;~8r2pit~|)`hRk8tcHUEG
                            z(@ljp?kV?W=dyoEHC9#h@++_Y>Xo1U>XmdRLq45Bd)!hiqG+tHlOjn~0h(H=?2MPQ
                            znXbYuY?`OdzWZog6^kkx*i=(Ao2Hg$L@N>{Zg>OWk2k<9P(!Jn-)1UrkQH*}@|zj*
                            z7D;Ke##3ZT_FEnvJqQko0x;Qc*_XNi&@{JNG!3xbz7l`@!Aw^w0|Eq0T}cB%g;Q79
                            zvuW8OoskFzpz=%wz!9qOgF}rYZfxfblUfRDgXuc85C(N3%r%u+C&jK>Qr>94ZdLNv#c;EqrpR2c1OAe9
                            zERj3un>ae+1M<@A*`c05>Js^sz&KR5nW5VV1hgZW2$IDMd#713G+SQl#tq8?SN5(x
                            z0>i0+0jP2WLN{9q2TbyTAseydl8L-rB8V?d9*}S;Nm@@8-Q*$wcdrmN%dCm>fa2b86YK<*`}uKTt(Lc7E*Jr
                            zH_oNfft}wI4kdfLPUzd+ZW!AhF-rtpYPe66+O|@st9(bJfKfNBrlR@aa@j?h54Fi)
                            zfUbXvqk(WhJa^$|7TCwXne;jV_4&fNEcF0?_A`KjUkKt0VOmBNh`wP%iog@d{(Q-v
                            zbc@k#U`wccsLul*n$leh2xQepSqbY)=UtyEzb)Cw67LSlH;sWSHgKgQ`l_KBXtzvn
                            zP>XSLiLj<=SX|M0+SiN+qG#9s!J$|cTzY@5FS5?1vP8sGK>y46SG}*?qE^}u?{Psq
                            z$Se=uz_gJDXH;N9mnN5r5YW6UNF@DTha$;`Fqg6+ZRJ?Mj)TI6lO$
                            z3P@*bExn5FO=f*?3cMKiKfe0mdslC*K}_{V`9QcXe7e(9-g^F>4{oi!eRb_>-UWYH
                            z_QmKn-ti27JzoP!+4+`kH&_kQho|5!yCd*GG*d@n$%$U0P%#dnpgJ0v+iw)Q9Jp`}
                            zgD>L~;6&Sqq3_j?-%V82c|drf;*(Kv>Oo2t7_;3Pt751-kfcA$Syfx_$o%yZ;LX^1)Zt=m+XOF(nODg?ABHdASL
                            zer4D^*Q8uY`S%tOFvI#Q&R$^RASW*{F@TwtLK+sW6;t_q0sd8?z^ohA4$RJsdq7%_
                            zwluK#25)Mq(rtN<+`xM)1w~HC!Up_a47N8k3|H#ojga+&th&9cxCt82r&52{++Jd)
                            zC3*!>3(Y9aC^`TTJdC3q16qMvw|8fyU}*Bno#*x%5_ce)NAf{eQya`DjHFGM%p3($_w{!V#IVn
                            cFP=T`3l%E`3`Mw5f@WO$KM%-Px#
                            
                            delta 6564
                            zcmV;V8C&L&Hj6f}q5*#{6$&+=z|PkVqpnfKWOlx4G!e&JHKob4o#O2V(+t}%8`OHu
                            zZdFhv8pv7CR(C9>X{?$SM5TK~r3v3LX)(>|eU6yY6OI3lVYQmx$disadbkhlZADY3
                            z%+p7emd;yqHx1pG@<_MW=2jKmjy}qmhKA$klx=E*d*z!<_qBhwF>y7OF8oYn;EHC{
                            z`v#8$TW7q{ssy`A$`!W8HfU4fjl9(=)F@T$f}&}8g&WQM{ic?ZB26i#2^OkgBq(6p
                            zoM;oIC>p1hu5buZB9s(U&bQ7>=g9eiys`L8aus@$cK~sU6k-r!*>(^e&@?_7AFi(Y
                            zP$9z`v90Q$0Plaag<@};B2Mqcv1qthFrqGM_D-}cC=^NvC
                            zb{q_Vrk6})G_P3@OH-xa8ZDw&l(cN7*NLJ7rQ9;~ddX;U6?jx(czJ_VEMwcIR-W7j
                            zXR#?+Q3k~-+Z!Ob9pOi*Qp>Dcib~0j(Xu@7m4Z?thBbc#y}iBdI-+#K9+8E&EUGe#
                            zR(X+IEudMca<&Duk#|LZa$WQ#?_g(vo*RTUP0QGFho<*UYB8!;X?~?(_DifUmGO}zl8ObqPz$VDq*!W+yEap4MX^$zIPp4XHx$*__PnQ2w~UtQ_U1Gvq5Hi<=`{))
                            z8t^U9d1HUEw8Fd*7^JzJ3FI>k&4HCjzrle;Kxbfkrcc#f?3h@gaJX$5_dtN;MoR-W
                            zoIL_5`(fu1r0AEOuOMR|LB{Ti1~3W++$&w#>cidA1ai2UL(j60cL5T`L3SF}-GZHq~dg
                            zw~cKIE0;0(4XxKfV>TbIpnSxj
                            zSe$=V!3SMa6~IuDSvx*<(JfYiN4LM|I_w`qP@FXf$G{sYf)NTo6;q4z3vcA+ujCf4
                            ztSwww`o;Xx{QTVf>+m~8%vJ^a1!EUQ?B6?&$ifxk{H5~^`UF9Q!Sobx)DU`)SsG9b
                            z3EE&r&ca-(Gn)HEQI%?g9?Y=cihjvElJTULiD#4I`A0aZuNlg=OD_cNgGz&Rr5-OdYeAMnfr5m$Z$`Z3Zx
                            z#nwINIeP44*+IB2Hg>-3{DB}#ori$)CFwjw=sm&nL0^n|0WF=+;nsn?!1%R~-k*O3
                            zX!KdYi5MZ$?2^}Bd2?}bei^Rz@fuJ)h3m>PXNb(g#E1Z7?{~d
                            zQHvHq8r*r>`FxN@$;%;p{sG3t!I4!05T8T$U9hGee;&CKw!pg+7W_Y*Xp#5$k`ORO#-layJ7R92!a(^?kck`nm{WVDz^0TnKts
                            zj0oHSt&e5%OCawHX^?me#o#|ODU!R8f-OiB^i!q0K$P+#xvQxLx8bAyU<}FzP*ea#
                            zrH7(YZuX-<;$VF(~x
                            z;nWAhcn$~sXP`i`p+a&KAjK4(*D1#vFkf#LFVCk+prOw@k7SZ@NBlFW>aoBG`f6kL
                            z%?=EO$~;70?0nVp9~7hTAq+fV3et5^+lQSm!6cz^S2R6AIeQi=90`L#*DR60JqTR;
                            z(zVc%o(UW7B7y*L2sS2&kv@NfXwmGz-BC06Ul2q@!~;seaX^fnuZ2e)bUr5-d(aqN
                            z`vh1w_JAD#v-_xC8Hje})sJ4^ti%j-wuMXt0lycvBO(skHK5z=HTLNY#kx;~7XTGG
                            zDY+*?!Miw8zvBaJ76Y2>?X~?8$3{1MB22c8N&xQuEGi^v0fM+bGJS%>a!wJ5yn3(tI9
                            zLqI-U+!%=@U(bQFyt@K-B+AA^TE-ydltMDC&VI-uCzD
                            z5AJHT#%IYba@S(@2G4)=#gQYIu{OlwJ?8}s{U>2Ju6MdA*cE5bZw@+Ndd`Jv?vue&
                            zS314;?@yFD5SNZb(%W}Kfn
                            zvnR$A@lb{uH{0)_WgN3G=Y=~?kKi60;B4a`jJ3}KMJWx!%#zI^oAC2XZ}x;p54yDg
                            z(gqHP#`Am7zz>+@abU0~2!&YB?4u07c1x9>wGa3$K(>j9M1nmGXdg(PE&@Gn4RUqI|D*QB!^VMO&QbOvfJIoSh-
                            zMaUCnp-3hoU5T1SW*$*Q4KN{;@(>yiggbubnJk(eW+PW?BEkRy^y0&Q&%jzYNF#vZ
                            zAdem+1M&e8!C2bpk%-kYFiQD>nMal%k|mOPx5ANi>7jpHXpVt*GfPY#yoY{8{8Qiv
                            zIXT4Kfl&?(QrLLc?$Mq*f9O_)Ui^id0O0z%E7P90e=mv)^oFncXEJT#twrGAKL|mi
                            z?4Au&DT379rGOlOB==>aeUZWU(HP3bd6bJ
                            zI1-iE7k$$(81-8Sj=LBY-6Ck9SbHLU3vL{Vg5Xb3XW^_y%tMc}i3&o;mi~eD5{&x2
                            zn8KiQw6mjWcsf9_AO-W~!(OG*H`ja7Rj$1FNqB#yRIgV-lZE+LWdb}DYz$OI$436C
                            zTbCaUnk}&2HQeult72hEm{}z%9A)2^+P(hb+tZndWkdifN}x*WP{K4Hp?#BDj|1c49m!Ue#JE
                            z^&-)+4z*P2HH|MbAkm^q^R+r(c6$zC^6tw&GYM0mXm!J4ym5*oY{9J0uugA$oAT2e
                            zys4O{H+a?ND$^6;emVqJ(1#0k^x=Y{-cx_7RIl!oarHLeFi%Txn=OMcn-*(Qo6#*Q
                            zC=vHgQidC;lGxMor4t(QC;{B6`ZJ=ZN}zf_dV$>KII^3V9--<}Wv`v2dyA+tOsI(tOZ3iD<`9L%}l32iTU`
                            zvK!@!Qr(DXlOYm$HBcZ6^FijiJRyJMA>%yRL;K!drpKYc_~{L+_Sqv6E8}
                            ziDRcGY*U(M5I!|Hzh@>%zH8Af*H@1HiD{xRJSKrKtE#rFa!hB$3=6K7GH9
                            zYlF9e`ot#jVzn{qs*p|j>6d>xa-H;CtU#Pkdz;P@NLV@3m;A>sXhK%CCN{`%-7CzC
                            zPPSg;;GOIfS`M74uxJ7ftAv*$kAd1qvh+h%153XkB60~a8d^k7tA-2=W!UbGChq{RzMI(7XfX_BFfnwfv3HsXBk3{n`Y
                            zMceQgm1d)IUt_`S2Y_rYL@Fyo7c^qg9ICO1eoy?X>i*LD>?vUJ94H_`xyEp6g-4Vr
                            zOGu=lOSpl1j-N)h+SA-$Y$_YH95ic-6F9Pw4Lx#xPjEf!Vl52rFQiI^0y!f+06{$4TZZOnNEN3H7_=)wBXie)`VL&(G4E+oYT2ke8Xwxmci7(B86(#6!iwm
                            zW=cijKf@Z!hy^YhBEE?>^O}koRlullrt{0cDDy}Ks|y!r`3biY>_`)G*Ja&j^lkXi
                            z(z#8H8ZpVw$!3Ce?o_w+G%)4>zL$c86>2L}Iqx%U5ko|6(4BwCGf6XYacSAncfz8M
                            zVpA|GbsGC-F(ybOd?Ud!yr;kf>hL%;hn3-@j<-!xX@=2yC$g~CBkuZ+vlJQE*r?V!
                            zt#$SVG+p^5c@XYmZzzGip^G$nkw(u-8ci~a1&6W4f06|gGpVE1Lu|N3J$j}$>&Dr*
                            zMHO|2(EH5pY4CqM=d<}~c*SY00immJD`sM+!n3jB^~KSu37$+knIk@O>+mC;ZQg1%
                            zFP4hV-cr$tnZZRtd795*G2NyXPblY)Q)4Fn2-X?pIke*K9Zv7Qa`IxM=AZh|@~C|i
                            zJV!&Rx=N$kW&e}bkupa;YRMJ&Og9X)v=o@CEl%&3y)S<&2#Ct!-2qXuY}oFC*o88A
                            zV(|DdTwjoY2Ka7ZTih8e%h|c^(0!*qL5IFUNnO?oy)UjkO>={;B&u!YADojA~p-FQ{_Gsz<8=L!K24kxMpWU6|~7;i=Ep
                            zExJ|SiaKczFPJhXzfTck>prf%#(YpB?r>on{Mq0Wy&+o7MBIg$67f?zop5~GKCSm^
                            z1wG*%>==nIv`oHI6es?~@Xh{7W|W=3g~WFLq7;A0NvEk1p>ona-9#*Xl2x;_ki;VA
                            zuTk-AG7C%gk)DyW>BOFYh@3FOW;rKEc5on^YL3A}v`lZ&DZMKs_CjYpVja5`v43bd
                            zkN)IvHpxY~D2q>#vcieHHRWVB1HxB?@vA-~z4j{{9n8_Hk&naU7YqlUvoBDs0>H|3A7z8~X2=e+xqbheMZn1!5bM!<`QN32C{l|vspoP?R)`=O(*
                            zvel_hErru?+JYkQpk~Lj_mRuF;V*Gnp7zOw_zL$MF`isU2qEE#dd$%hc`s(HDQ7Qh
                            z`4(t_%Cx=rso!cfE7THC0SV6W{NTV_)uVsmjW5GkFDn^E3n)gLM#PNAVpXGxHS%42
                            z)3B2%9|j8z6l3pI$I2$7c0DvLbf4)=9iOtIPGv{L)QM-ZVVg9(yT%ylMJTb~(Pl>8
                            z+O`wSpZ>wu+=;qx5x6j$?5mxlk2B6v^AK%Hb)ziTFKN_w0gQ6YOy;znRhm4ft~GzC
                            zMTr9cC(ERxWOQ<=w9A@&qJJ{Brj(T9KUF`{7MD-eoUYdJ+uMOX%9&m#6-AX=Sh_H;
                            zlQJ*&F`Iv-#L%@JqEo68-hfhhFvG-|hz%yGNVzoTlL1pT_ZV+aIGwX^6Rls2T4!87
                            z`S(wZQE{K4(?~*iVjE@(5)3}>8?t{yelZgW-8CI$@pl4GTBv1dF$ryDWY(iU?rWW;
                            z$KlVy9_UDQPHZqE9sEwjEvZtNK2$la7pkL~qWD-fM*V#ZaN@MKeDPewL|^}480tAV+P;4k=V-f+
                            zolf55fm0s
                            zGXEdmqc!wp8RM_31cOZ&;mdaLa@V>4B9Zw-zepsGUB_DSJwsprG5K2iyC59`!H>K$
                            z*&;LxF#fqw-=`Rp?qhoa$-aL*Y^1S^I45(CJ5a!rzank4ea;0xwW%d!povDSP-Tv}(Kfws5wXNcTr$aQ|M}MbBPx)y
                            z@;wWK=00}C%g)wOj2KVS;QTab`V~`mv}y94sXxbJX>~3r$Dgb$t1oLzu^>Fhbrq4lZL1}t9@=LhEqn%Z#l8Fv2(E{-~Xbau1E
                            z+3P%XeuBO)J6}1^JD+#HAwGm&d$;?b5_SdTJ5H@Wwsm
                            zzU*8!sm7{`UVeY&)nC2xvtPZE&Sc1^GiZ-nibWKS)pb%NsVYEIE0vw`ayHXdxP?vg
                            zwAptbjjLi&WdoaPie}T)@{DLjqQnhv0Q~U=m<4Jm)$`j-NKbYxCWk7#`fT=5KK&Wu)3VSv!JESub
                            z!2ndAsQ@@a6@GB2afCdkbKkzURmH9i&P{u%P^hZR*)m`Fr+TRYR|_dU1{ZCU^DbYVPLE_shRtyZOFh!6(0Q@62w4
                            z+>PzLVN!ofL2WQyrxwDXPK3FpGV7$+RZGen?boeJ{<;`$_R|!Z>vh0il8z;ECw&t~
                            zM|?nDdObVT6G&YmpAr~{>NYcU8-aj!Bojfhcwz4}D~4vvYu&hES>Vdv)kk1BH822G
                            zjzH*UOW}Y?J}_h>c3d)%mrDfkrO5;GV3-yV3yy!zbhE_^Kp3ExpOI$}U^WfaE?y%)
                            zx$CQ|ehdwA0s>sTCv*eQ&8F775ICvc>RtVtVKf7zq%zyol%1>STEIeT&h^H*R64Np
                            zd%~e)Z`TQZyW0(8+aqR)pi2$+X;Rx(>U5RwXcRE&hSgLwA6zcGDD$B<84S=>aWoJP
                            zi06MU{LBLT_&1YYC!juGIG3d!;Lm;rQ1A;ud?8HBr~=V9Y)BD!0@8(HGrA^D~;aK#3$bVOe@Gz0CH=?!WzPA(DF
                            zG!2U@I#2tW@j&$K+CMlHtAb0<^+ndXRF;2;mwXf~0DfL@Qlg_3apzU<#
                            z&ir~Nub3uG(XKa`rp^u&Do~g`fO&t8yeJJZ=e~8D3Udi)ZdiqY7R6>N?ar?Zo9CL8
                            zD=Gip0s>}Of5q7gOdRCo1ttbC(^5#oqP1cwpD)0_DioM?!`gw_nQ;$D%h8qw7T@4a
                            zEmgWL?~xmLZ>6Bf30c^H-;2TahKAuveY_E}evnnScNI551Nv0zn%hgvv_yZeAZno*
                            zr5QyB0D^~cv|~UkQ0w;YtP~7QUb*w!UW1(Wj+kf7$oW9oR5l?}h(BPNch=En@hXpN
                            z-?LD#SxR-|Hq<&FLrsug&m3>3x>C{T`%K?h!=6m9yPameXf@kED{B=~UQKVZZMKou
                            z*aj7~t<@^H4%3g`rd;5q)<=I96j-D+mzHp5!*mB40$637zNbRx^g_1_j;$6w$IFs>
                            zQ4N~%WQh%p{;uiu0q2x>>ta?@9G=rai(>ES)gl&Jcm)B3THPy{-xRyNK#jXh?7RsR
                            z8=c=WRGOF1W?rK;!=khGtSz{BkeP+QU8nCYK}$s=O3z3eKzZRFPK+Fw4(P?R=Y64K
                            WrGTLb7fR5KOaBMp-7b+=zW@LT?x64h
                            
                            diff --git a/posts/nakhozhdenie-summy-k-ykh-stepenei/index.html b/posts/nakhozhdenie-summy-k-ykh-stepenei/index.html
                            index 68a70ec..e663ac2 100644
                            --- a/posts/nakhozhdenie-summy-k-ykh-stepenei/index.html
                            +++ b/posts/nakhozhdenie-summy-k-ykh-stepenei/index.html
                            @@ -1,4 +1,4 @@
                            - Нахождение суммы k-ых степеней Нахождение суммы k-ых степеней
                            1. Нахождение суммы k-ых степеней

                              Давайте сразу обобщим задачу до нахождения \(f_k\left( n \right)\), где

                              $$f_k\left( n \right) = 1^k + 2^k + \ldots + n^k$$

                              Для \(k=1\) формула известна всем школьникам: \(f_1\left( n \right) = \frac{n\left(n+1 \right)}{2}\). Формулу для \(k=2\) знают уже не все, но всё же в школе её найти можно (я видел на обложке учебника по алгебре): \(f_2\left( n \right) = \frac{n\left(n+1 \right) \left( 2n + 1 \right)}{6}\)

                              Интуиция может подсказать, что \(f_k \left( n \right)\) есть некий полином со степенью \(k+1\). Если это так, то его нахождение тривиально. Например, можно посчитать его в явном виде, используя полином Лагранжа. Осталось показать, что наша функция представима в таком виде.

                              Для начала введём обозначение. “Нижней степенью”, \(x^{\underline{k}}\), будем обозначать такое выражение:

                              $$x^{\underline{k}} = x(x-1)\cdot \ldots \cdot (x-k+1)$$

                              .

                              Далее, заметим следующее, если \(a_i = A_{i+1} - A_i\), где \(\lbrace a_i \rbrace\) и \(\lbrace A_i \rbrace\) — некие последовательности, то \(\sum_{i=1}^n = A_{n+1}-A_1\) (телескопирование, можно посмотреть тут, с. 6).

                              Теперь посчитаем сумму \(\sum_{i=1}^n i^{\underline{k}}\). Для этого достаточно понять, что \(\left( x+1 \right)^{\underline{k+1}} - \left(x \right)^{\underline{k+1}} = \left( k+ 1 \right)x^{\underline{k}}\). Отсюда сразу получаем, что

                              $$\sum_{i=1}^n i^{\underline{k}} = \frac{\left( n+1 \right)^{\underline{k+1}}}{k+1}$$

                              Осталось показать, что “нормальные” степени выражаются через нижние. Начнём со степени \(k=1\), тут всё просто:

                              $$x = x^{\underline{1}}$$

                              С бОльшими степенями сделаем следующее: считая, что все степени, меньше, чем \(k\) мы выражать умеем, раскроем скобки в определении нижней степени. Теперь поймём, что старший коэффициент \(1\): \(x^{\underline{k}} = x^k + \sum_{i=1}^k a_ix^i\) или \(x^k = \sum_{i=1}^k a_ix^i - x^{\underline{k}}\). Осталось понять, что каждое из слагаемых вида \(a_ix^i\) мы умеем выражать через нижние степени. Таким образом, можно получить следующее:

                              $$ \sum_{i=1}^{n} i^k = \sum_{i=1}^{n} \sum_{j=1}^{k} a_j i^{\underline{k}} = \sum_{j=1}^{k} \sum_{i=1}^{n} a_j i^{\underline{k}} = \sum_{j=1}^{k} \frac{a_j \left(n+1 \right)^{\underline{k+1}}}{k+1}$$

                              Кстати, формула для суммы в самом начале такая:

                              $$ \sum_{i=1}^n i^5 = \frac{1}{12} n^2 \left(n+1 \right)^2 \left(2n^2 + 2n-1 \right) $$
                              Wallabag и реальная жизнь
                              1. Wallabag и реальная жизнь

                                Начать следует с того, что Wallabag действительно является самым популярным среди открытых приложений для отложенного чтения. Можно взять, например, alternativeto:

                                Первый релиз вышел почти два года назад. Тем не менее, мне сложно назвать продукт зрелым. Последняя, на момент написания, версия 2.0.0-beta.2 не может похвастаться простым процессом установки. Вариант просто выполнить команды из мануалов по очереди у меня не получился. В этом соперничать с тем же Pocket, очевидно, бессмысленно.

                                Стандартная тема, material, ужасно выглядит на моём ноутбуке с разрешением 1366x768, элементы явно рассчитаны на большую диагональ. Ещё часть места отъедает неубирающаяся плашка внизу страницы, предупреждающая о том, что баги в бета версии не есть что-то плохое. Официальное Android приложение упорно не может найти сервер.

                                После волевого решения перейти на стабильную версию (то есть откатиться в равзвитии на полгода назад), дела улучшились, но не сильно. Количество настроек минимально, если не сказать, что их вообще нет. Но оно работает, вроде.

                                Сложности, впрочем, только начались. Обещанная синхронизация с Pocket работает, мягко говоря, неоптимально. После загрузки экспортированного html файла со ссылками, wallabag почти час выкачивал мои 750 статей. Где-то на 500-й статье он выделил слишком много памяти и упал с ошибкой. После этого пришлось руками искать потенциально проблемные статьи и удалять их по одной — удалить сразу несколько элементов невозможно. Затем надо было выкачивать ещё 250 статей, периодически посматривая, чтобы ничего снова не упало.

                                Кажется, что все проблемы закончились, но нет. Дальше синхронизация с телефоном. Она заняла почти столько же времени, при этом, начальное очевидное предположение о том, что токен безопасности вбивать не нужно (он сам заполняется в приложении) стоило где-то 15 минут поиска. Но и это не всё. После того, как база загрузилась, небольшие изменения на телефоне (такие как удаление статьи) синхронизировались больше минуты!

                                Резюме: пользоваться можно, но советовать кому-либо это использовать я точно не стану.

                                Этого бы поста не было бы, если бы я сказал, что Wallabag плохой, а OTHER_PRODUCT хороший и можно пользоваться им. Но я так написать не могу. Ни я, ни alternativeto других решений не знают. Значит нужно их создать. На моём слабеньком VPS уже почти год трудится Syncthing, управляя значительным количеством файлов с минимальной нагрузкой на ЦП. Поэтому мне кажется, что Go подойдёт идеально.

                                Если написать подобный продукт на Go, то многие проблемы даже не появятся:

                                • не нужно разрешать большое количество зависимостей — достаточно одного бинарника
                                • скорость генерации контента (например, создание pdf, epub) будет значительно выше
                                • небольшой оверхед позволит всё хранить в памяти
                                • работа почти на чём угодно

                                В совокупности, будет достигнуто, как мне кажется, самое главное — удобство для обычного пользователя, который сможет без проблем развернуть это на любом VPS.



                              Блог 529 - BGL
                              1. Моё решение задачи 60

                                Краткое условие: необходимо найти множество из пяти простых чисел с минимальной суммой такое, что после “склеивания” в любом порядке любых двух чисел из него тоже будет простое число.


                              Page 1 / 1
                              Блог 529 - блог

                              Page 1 / 1
                              Блог 529 - бот

                              Page 1 / 1
                              Блог 529 - c++
                              1. Моё решение задачи 146

                                Краткое условие: необходимо найти сумму всех натуральных \(n\), что \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будут последовательными простыми числами.

                                Блог 529 - FLINT
                                1. Моё решение задачи 146

                                  Краткое условие: необходимо найти сумму всех натуральных \(n\), что \(n^2+1\), \(n^2+3\), \(n^2+7\), \(n^2+9\), \(n^2+13\), и \(n^2+27\) будут последовательными простыми числами.

                                  Блог 529 - Go
                                  1. Wallabag и реальная жизнь

                                    Как я устанавливал известнейшее свободное решение для отложенного чтения, и что из этого получилось.


                                  Page 1 / 1
                                  Блог 529 - lichess
                                  1. Экспорт партий с Lichess

                                    Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.


                                  Page 1 / 1
                                  Блог 529 - математика
                                  1. Нахождение суммы k-ых степеней

                                    Как придумать формулу для суммы \(1^5 + 2^5 + 3^5 + \ldots + n^5\) и есть ли она вообще?

                                    Блог 529 - open source
                                    1. Wallabag и реальная жизнь

                                      Как я устанавливал известнейшее свободное решение для отложенного чтения, и что из этого получилось.


                                    Page 1 / 1
                                    Блог 529 - проект
                                    1. Экспорт партий с Lichess

                                      Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.



                                    2. CrossGen v1.0

                                      Читая хабр, случайно натолкнулся на идею сделать программу, которая по заданной кроссвордной сетке находит способ её заполнить. В этом посте вкратце напишу про моё решение и первую версию приложения.


                                    3. Ещё одно вычисление выражений

                                      На хабре когда-то увидел статью про то, что в Яндексе двум сотрудникам дали задачу на написание приложения, для вычисления выражений. Менеджер справился за 4 часа, а программист за два. Я решил попробовать свои силы.


                                    Page 1 / 1
                                    Блог 529 - Project Euler
                                    1. Моё решение задачи 134

                                      Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

                                      Блог 529 - Python
                                      1. Моё решение задачи 134

                                        Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

                                        Блог 529 - шахматы
                                        1. Экспорт партий с Lichess

                                          Сохраняем себе шахматные партии с Lichess.org. Рабочий скрипт на Python прилагается.



                                        Page 1 / 1
                                        Блог 529 - sympy
                                        1. Моё решение задачи 134

                                          Краткое условие: назовём порождающим для двух последовательных простых \(p_1 < p_2\) наименьшее натуральное число, что оно закачивается на \(p_1\) и при этом делится на \(p_2\). Необходимо найти сумму порождающих для всех \(p_1 \in \left[ 5; 10^6 \right]\)

                                          Блог 529 - wallabag
                                          1. Wallabag и реальная жизнь

                                            Как я устанавливал известнейшее свободное решение для отложенного чтения, и что из этого получилось.


                                          Page 1 / 1
                                          Блог 529 - wxWidgets
                                          1. CrossGen v1.0

                                            Читая хабр, случайно натолкнулся на идею сделать программу, которая по заданной кроссвордной сетке находит способ её заполнить. В этом посте вкратце напишу про моё решение и первую версию приложения.


                                          Page 1 / 1
                                          Блог 529 - Tags