<ahref="../../posts/moio-reshenie-zadachi-60/"rel="bookmark"><h1>Моё решение задачи 60</h1></a>
</header>
@@ -67,15 +67,15 @@
<p>Пусть мы получили набор таких разбиений, то есть набор пар вида <spanclass="math">\(\left( p, q \right)\)</span>. Давайте составим из них граф, где вершинки это простые числа, а ориентированное ребро из <spanclass="math">\(p\)</span> в <spanclass="math">\(q\)</span> означает, что есть пара <spanclass="math">\(\left( p, q \right)\)</span>. Из того, что порядок склеивания чисел произвольный сразу следует, что рассматриваемый граф должен быть неориентированным. Таким образом, все пары <spanclass="math">\(\left( p, q \right)\)</span> для которых нет пары <spanclass="math">\(\left( q, p \right)\)</span> необходимо выкинуть, а из оставшихся построить граф.</p>
<p>Теперь задача стало гораздо понятнее: достаточно выбрать клику размера 5, что сумма значений её вершин минимальна. В общем случае, это достаточно ресурсоёмкая(как мне кажется) задача, но в реальном графе количество рёбер не слишком большое. В худшем случае, по теореме Турана, количество рёбер в графе лишь с одной такой кликой примерно на 10% меньше числа рёбер в полном графе.</p>
<p>Непосредственно сам поиск такой клики можно реализовать тривиально. Ниже мой код на C++11 с использованием библиотеки Boost Graph Library (<spanclass="caps">BGL</span>).</p>
<spanclass="code-line"><spanclass="n">map</span><spanclass="o"><</span><spanclass="kt">int64_t</span><spanclass="p">,</span><spanclass="kt">int</span><spanclass="o">></span><spanclass="n">mults</span><spanclass="p">;</span><spanclass="c1">// contains counts of p * q</span></span>
<spanclass="code-line"><spanclass="n">cout</span><spanclass="o"><<</span><spanclass="s">"Good set #"</span><spanclass="o"><<</span><spanclass="n">i</span><spanclass="o">+</span><spanclass="mi">1</span><spanclass="o"><<</span><spanclass="s">": "</span><spanclass="p">;</span></span>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
<p>Давайте сразу обобщим задачу до нахождения <spanclass="math">\(f_k\left( n \right)\)</span>, что <divclass="math">$$f_k\left( n \right) = 1^k + 2^k + \ldots + n^k$$</div>
Для <spanclass="math">\(k=1\)</span> формула известна всем школьникам: <spanclass="math">\(f_1\left( n \right) = \frac{n\left(n+1 \right)}{2}\)</span>. Формулу для <spanclass="math">\(k=2\)</span> знают уже не все, но всё же в школе её найти можно (я видел на обложке учебника по алгебре): <spanclass="math">\(f_2\left( n \right) = \frac{n\left(n+1 \right) \left( 2n + 1 \right)}{6}\)</span></p>
<p>Интуиция может подсказать, что <spanclass="math">\(f_k \left( n \right)\)</span> есть некий полином со степенью <spanclass="math">\(k+1\)</span>. Если это так, то его нахождение тривиально. Например, можно посчитать его в явном виде, используя <ahref="https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D1%87%D0%BB%D0%B5%D0%BD_%D0%9B%D0%B0%D0%B3%D1%80%D0%B0%D0%BD%D0%B6%D0%B0">полином Лагагранжа</a>.
Осталось показать, что наша функция представима в таком виде.</p>
<p>Для начала введём обозначение. “Нижней степенью”, <spanclass="math">\(x^{\underline{k}}\)</span>, будем обозначать такое выражение: <divclass="math">$$x^{\underline{k}} = x(x-1)\cdot \ldots \cdot (x-k+1)$$</div>.</p>
<p>Далее, заметим следующее, если <spanclass="math">\(a_i = A_{i+1} - A_i\)</span>, где <spanclass="math">\(\lbrace a_i \rbrace\)</span> и <spanclass="math">\(\lbrace A_i \rbrace\)</span>— некие последовательности, то <spanclass="math">\(\sum_{i=1}^n = A_{n+1}-A_1\)</span> (<em>телескопирование</em>, можно посмотреть <ahref="http://www.mi.ras.ru/~scepin/interpol.pdf">тут</a>, с. 6).</p>
<p>Теперь посчитаем сумму <spanclass="math">\(\sum_{i=1}^n i^{\underline{k}}\)</span>. Для этого достаточно понять, что <spanclass="math">\(\left( x+1 \right)^{\underline{k+1}} - \left(x \right)^{\underline{k+1}} = \left( k+ 1 \right)x^{\underline{k}}\)</span>. Отсюда сразу получаем, что
<p>Осталось показать, что “нормальные” степени выражаются через нижние. Начнём со степени <spanclass="math">\(k=1\)</span>, тут всё просто:
<divclass="math">$$x = x^{\underline{1}}$$</div>
С бОльшими степенями сделаем следующее: считая, что все степени, меньше, чем <spanclass="math">\(k\)</span> мы выражать умеем, раскроем скобки в определении нижней степени. Теперь поймём, что старший коэффициент <spanclass="math">\(1\)</span>: <spanclass="math">\(x^{\underline{k}} = x^k + \sum_{i=1}^k a_ix^i\)</span> или <spanclass="math">\(x^k = \sum_{i=1}^k a_ix^i - x^{\underline{k}}\)</span>. Осталось понять, что каждое из слагаемых вида <spanclass="math">\(a_ix^i\)</span> мы умеем выражать через нижние степени. Таким образом, можно получить следующее:
<ahref="../../posts/wallabag-i-realnaia-zhizn/"rel="bookmark"><h1>Wallabag и реальная жизнь</h1></a>
</header>
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.