<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.157.236&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.157.236&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/217.66.157.236"/>
		<updated>2026-05-19T18:00:40Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B_%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D1%85_%D0%BA%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BE%D0%B2&amp;diff=67698</id>
		<title>Методы получения случайных комбинаторных объектов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B_%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D1%85_%D0%BA%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BE%D0%B2&amp;diff=67698"/>
				<updated>2018-12-08T18:54:28Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.157.236: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Необходимо сгенерировать случайный комбинаторный объект размера &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; с равномерным распределением вероятности, если в наличии есть функция для генерации случайного числа в заданном интервале.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; B = \{b_1, b_2 \ldots, b_k\} &amp;lt;/tex&amp;gt; {{---}} множество различных элементов, которые могут находиться в данном комбинаторном объекте.&lt;br /&gt;
&lt;br /&gt;
Будем получать элементы по порядку: сначала определим, какой элемент будет стоять на первом месте, потом на втором и так далее. Считаем, что мы построили префикс длинны &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt; P = \{a_1, a_2, \ldots, a_i\} &amp;lt;/tex&amp;gt;. Будем выбирать элемент &amp;lt;tex&amp;gt; a_{i+1} &amp;lt;/tex&amp;gt; из множества всех возможных так, чтобы вероятность выбора элемнта &amp;lt;tex&amp;gt; b \in B &amp;lt;/tex&amp;gt;, была пропорциональна числу комбинторных обьектов размера &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; с префиксом &amp;lt;tex&amp;gt; P + b &amp;lt;/tex&amp;gt;. Для этого разобъем отрезок натуральных чисел &amp;lt;tex&amp;gt; [1, s] &amp;lt;/tex&amp;gt;. где &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; {{---}} число различных комбинаторных объектов с текущим префиксом, на &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; диапазонов так, чтобы размер диапазаона &amp;lt;tex&amp;gt; d_j &amp;lt;/tex&amp;gt; был равен числу объектов с  префиксом &amp;lt;tex&amp;gt; P + b_j &amp;lt;/tex&amp;gt;. С помощью функции для генерации случайного числа получим число &amp;lt;tex&amp;gt; r &amp;lt;/tex&amp;gt; в интервале &amp;lt;tex&amp;gt; [1, s] &amp;lt;/tex&amp;gt; и добавим к префиксу &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; элемент &amp;lt;tex&amp;gt; b_j &amp;lt;/tex&amp;gt; соответствующий диапазону отрезка в которм находится полученное число.&lt;br /&gt;
&lt;br /&gt;
 '''object''' randomObject(n: '''int''', k: '''int'''): &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} размер комбинторного объекта, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; {{---}} число различных элемнтов.&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 1 '''to''' n                               &lt;br /&gt;
     s = number(prefix) &amp;lt;font color = green&amp;gt; // число комбинаторных объектов с текущим префиксом. &amp;lt;/font&amp;gt;&lt;br /&gt;
     r = random(1, s)&lt;br /&gt;
     '''for''' j = 1 '''to''' k  &lt;br /&gt;
       '''if''' number(prefix + B[j]) &amp;lt; r &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; {{---}} множество всех возможных элементов. &amp;lt;/font&amp;gt;&lt;br /&gt;
         r = r - number(prefix + B[j]) &amp;lt;font color = green&amp;gt; // если &amp;lt;tex&amp;gt; r &amp;lt;/tex&amp;gt; не попало в текщий диапазон {{---}} перейдем к следующему.&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''else''' &lt;br /&gt;
         prefix[i] = b[j]&lt;br /&gt;
         break&lt;br /&gt;
   '''return''' prefix&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(nk) &amp;lt;/tex&amp;gt;. Количества комбинаторных объектов с заданными префиксами считаются известными, и их подсчет в сложности не учитывается. Стоит отметить, что подсчет количества комбинаторных объектов с заданным префиксом зачастую является задачей с достаточно большой вычислительной сложностью.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
Докажем по индукции, что вероятность получить любой перфикс &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; S(P)\over{C(n)} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; C(n) &amp;lt;/tex&amp;gt; {{---}} число различных комбинаторных объектов данного типа длины &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt; S(P) &amp;lt;/tex&amp;gt; {{---}} число различных комбинаторных обьектов длины &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; с таким префиксом.&lt;br /&gt;
*Любой комбинаторный объеут имеет пустой перфикс, следовательно &amp;lt;tex&amp;gt; S(\varnothing)=C(n) &amp;lt;/tex&amp;gt;. Вероятность получить любой префикс &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; S(P)\over{S(\varnothing)} &amp;lt;/tex&amp;gt;, что равно &amp;lt;tex&amp;gt; S(P)\over{C(n)} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Пусть вероятность получить префикс &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; равна  &amp;lt;tex&amp;gt; S(P)\over{C(n)} &amp;lt;/tex&amp;gt;&lt;br /&gt;
*Вероятность получить из &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; любой префикс &amp;lt;tex&amp;gt; P' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; l+1 &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; S(P')\over{S(P)} &amp;lt;/tex&amp;gt; , следовательно вероятность получить префикс &amp;lt;tex&amp;gt; P' &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; S(P)\over{C(n)} &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\cdot&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; S(P')\over{S(P)} &amp;lt;/tex&amp;gt; что равно &amp;lt;tex&amp;gt; S(P')\over{C(n)} &amp;lt;/tex&amp;gt;&lt;br /&gt;
Результат работы алгоритма является префиксом &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; и для любого такого префикса существует только один комбинаторный объект размера размера &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; , следовательно вероятность получения одинакова для всех различных результатов и равна &amp;lt;tex&amp;gt; 1\over{C(n)} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Битовые вектора ==&lt;br /&gt;
Рассмотрим алгоритм получения случайного битового вектора. В битовом векторе может находиться только два типа элементов: &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, следовательно &amp;lt;tex&amp;gt; k = 2 &amp;lt;/tex&amp;gt;. Заметим что для любого префикса длины &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; число возможных комбинаторных объектов длины &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; одинаково и равно &amp;lt;tex&amp;gt; 2^{n-l} &amp;lt;/tex&amp;gt;, следовательно на каждом шаге алгоритма небходмо выбирать с равной вероятностью &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''vector&amp;lt;int&amp;gt;''' randomBitVector(n: '''int'''): &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} размер битового вектора.&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 1 '''to''' n                               &lt;br /&gt;
     r = random(0, 1)&lt;br /&gt;
     v[i] = r&lt;br /&gt;
   '''return''' prefix&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма {{---}} &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;, так как в случае двоичных векторов &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; постоянно и равно &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Правильные скобочные последовательности ==&lt;br /&gt;
Рассмотрим алгоритм получения случайной [[Правильные скобочные последовательности|правильной скобочной последовательности]]. Правильная скобочная пследовательность состоит  из двух типов элементов: открывающей и закрывающей скобок, следовательно &amp;lt;tex&amp;gt; k = 2 &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;quot;полуправильные&amp;quot; скобочные последовательности т.е. такие что всякой закрывающей скобке соответствует парная открывающая, но не все открытые скобки закрыты. Такую последовтеьность можно охарактеризовать двумя числами: &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; — длина скобочной последовательности и &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt; — баланс (т.е. разность между количеством открывающих и закрывающих скобок). Заметим что любой префикс правильной скобочной последовательности является &amp;quot;полупраильной&amp;quot; скобочной последовательностью, и что для любого префикса &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; число различных правильных скобочных последовательностей длины &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; равно числу &amp;quot;полуправильных&amp;quot; скобочных последовательностей длины &amp;lt;tex&amp;gt; n-l &amp;lt;/tex&amp;gt; с таким же балансом как у &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Научимся считать &amp;lt;tex&amp;gt; D[l][b] &amp;lt;/tex&amp;gt; {{---}} число последовательностей длины &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; и баланса &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;). Если &amp;lt;tex&amp;gt; l = 0 &amp;lt;/tex&amp;gt;, то ответ понятен сразу: &amp;lt;tex&amp;gt; D[0][0] = 1 &amp;lt;/tex&amp;gt;, все остальные &amp;lt;tex&amp;gt; D[0][b] = 0 &amp;lt;/tex&amp;gt;. Пусть теперь &amp;lt;tex&amp;gt; l &amp;gt; 0 &amp;lt;/tex&amp;gt;, тогда переберём, чему мог быть равен последний символ этой последовательности. Если он был равен &amp;lt;tex&amp;gt; '(' &amp;lt;/tex&amp;gt;, то до этого символа мы находились в состоянии &amp;lt;tex&amp;gt; (l-1,b-1) &amp;lt;/tex&amp;gt;. Если он был равен &amp;lt;tex&amp;gt;')'&amp;lt;/tex&amp;gt;, то предыдущим было состояние &amp;lt;tex&amp;gt;(l-1,b+1)&amp;lt;/tex&amp;gt;. Таким образом, получаем формулу:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;D[l][b] = D[l-1][b-1] + D[l-1][b+1]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(считается, что все значения &amp;lt;tex&amp;gt; D[l][b] &amp;lt;/tex&amp;gt; при отрицательном &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; равны нулю). Этот преподсчет можно выполнить за &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем строить префикс следующим образом: на каждом шаге интервал случайных чисел &amp;lt;tex&amp;gt; [0, s] &amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt; s = D[n - l][b] &amp;lt;/tex&amp;gt;) , будет разбиваться на два диапазона размерами &amp;lt;tex&amp;gt; D[n - l - 1][b + 1] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; D[n - l - 1][b - 1] &amp;lt;/tex&amp;gt; , и к префиксу будет прибавляться &amp;lt;tex&amp;gt;'('&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;')'&amp;lt;/tex&amp;gt; если случайное число попало в первый или второй диапазон соответственно.&lt;br /&gt;
&lt;br /&gt;
 '''string''' randomBracketSequence(n: '''int'''): &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} длина скобочной последовательности. &amp;lt;/font&amp;gt;&lt;br /&gt;
   b = 0&lt;br /&gt;
   l = 0&lt;br /&gt;
   '''for''' i = 1 '''to''' n                               &lt;br /&gt;
     s = D[n - l][b] &lt;br /&gt;
     r = random(1, s)&lt;br /&gt;
      '''if''' D[n - l - 1][b + 1] &amp;gt;= r&lt;br /&gt;
        l = l + 1&lt;br /&gt;
        b = b + 1&lt;br /&gt;
        result = result + '('&lt;br /&gt;
      '''else'''&lt;br /&gt;
        l = l + 1&lt;br /&gt;
        b = b - 1&lt;br /&gt;
        result = result + ')'&lt;br /&gt;
   '''return''' result&lt;br /&gt;
&lt;br /&gt;
Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt; O(n) + O(n^2) &amp;lt;/tex&amp;gt; на преподсчет.&lt;br /&gt;
&lt;br /&gt;
== Разбиения на множества ==&lt;br /&gt;
=== Разбиение на &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; подмножеств ===&lt;br /&gt;
Рассмотрим множество первых &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; натуральных чисел: &amp;lt;tex&amp;gt; N_n = \{1, 2, \ldots, n\} &amp;lt;/tex&amp;gt;. Необходимо разбить его на &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; непустых подмножеств &amp;lt;tex&amp;gt; \{B_1, B_2, \ldots, B_k\} &amp;lt;/tex&amp;gt; с равным распределением вероятности.&lt;br /&gt;
&lt;br /&gt;
Будем строить разбиение таким образом, чтобы в результате подмножества &amp;lt;tex&amp;gt; \{B_1, B_2, \ldots, B_k\} &amp;lt;/tex&amp;gt; оказались отсортированы в лексикографическом порядке (т.е. чтобы для любых &amp;lt;tex&amp;gt;i, j \mid 1 \leqslant i &amp;lt; j \leqslant k &amp;lt;/tex&amp;gt; наименьший элемент &amp;lt;tex&amp;gt; B_i &amp;lt;/tex&amp;gt; был меньше наименьшего элемента &amp;lt;tex&amp;gt; B_j &amp;lt;/tex&amp;gt;). Для этого будем по очереди добавлять каждое число от &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt; в одно из подмножеств и для каждого из подмножеств начиная с &amp;lt;tex&amp;gt; B_n &amp;lt;/tex&amp;gt; и заканчивая &amp;lt;tex&amp;gt; B_1 &amp;lt;/tex&amp;gt; будем выбирать какой элемент будет добавлен в него последним(т.е. будет минимальным).&lt;br /&gt;
&lt;br /&gt;
На каждом шаге префиксом считаем текущее разбиение. Оно характеризуется двумя значениями: &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; — число добавленных элементов и &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt; — число подмножеств для которых определен последний элемент. Заметим, что количество разбиений на подмножества с заднным префиксом равно числу способов разбить еще не добавленные элементы на еще не законченные подмножества так, чтобы они оказались лексикографически упорядочены, то есть равно числу разбиений &amp;lt;tex&amp;gt; n-l &amp;lt;/tex&amp;gt; элементов на &amp;lt;tex&amp;gt; k-m &amp;lt;/tex&amp;gt; непустых подмножеств, что равно &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l\atop k-m}\rbrace&amp;lt;/tex&amp;gt; (т.е [[Числа Стирлинга второго рода|числу Стирлинга второго рода]]). Таким образом из префикса &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt; мы можем получить следующий префикс &amp;lt;tex&amp;gt; P' &amp;lt;/tex&amp;gt; двумя способами: &lt;br /&gt;
*Добавить текущий элемент (&amp;lt;tex&amp;gt; n-l &amp;lt;/tex&amp;gt;) в одно из &amp;lt;tex&amp;gt; k-m &amp;lt;/tex&amp;gt; незаконченных подмножеств. В таком случае число обьектов с префиксом &amp;lt;tex&amp;gt; P' &amp;lt;/tex&amp;gt; будет равно &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l-1\atop k-m}\rbrace&amp;lt;/tex&amp;gt; .&lt;br /&gt;
*Сделать текущий элемент последним в подмножестве &amp;lt;tex&amp;gt; B_{k-m} &amp;lt;/tex&amp;gt; . В таком случае это подмножество станет законченым, следовательно число обьектов с префиксом &amp;lt;tex&amp;gt; P' &amp;lt;/tex&amp;gt; будет равно &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l-1\atop k-m-1}\rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Таким образом на каждом шаге интервал случайных чисел &amp;lt;tex&amp;gt; [0, s] &amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt; s = &amp;lt;/tex&amp;gt;&amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l\atop k-m}\rbrace&amp;lt;/tex&amp;gt;) , будет разбиваться на два диапазона размерами &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l-1\atop k-m-1}\rbrace&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; (k-m)\cdot &amp;lt;/tex&amp;gt;&amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n-l-1\atop k-m}\rbrace&amp;lt;/tex&amp;gt;. Если случайно сгенерированное число попадет в первый диапазон, то сделаем &amp;lt;tex&amp;gt; n-l &amp;lt;/tex&amp;gt; последним элементом в подмножестве &amp;lt;tex&amp;gt; B_{k-m} &amp;lt;/tex&amp;gt; . Иначе добавим &amp;lt;tex&amp;gt; n-l &amp;lt;/tex&amp;gt; в случайно выбранное из незаконченных подмножеств (&amp;lt;tex&amp;gt; \{B_1, B_2, \ldots, B_{k-m}\} &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
 '''int[]''' randomSetPartition(n: '''int''' k: '''int'''): &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} количество элементов в множестве, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; {{---}} число подмножеств на которые нужно разбить исходное множество. &amp;lt;/font&amp;gt;&lt;br /&gt;
   l = 0&lt;br /&gt;
   m = 0&lt;br /&gt;
   '''downto''' i = n '''to''' 1                               &lt;br /&gt;
     s = stirling(n - l, k - m) &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; stirling(a, b) &amp;lt;/tex&amp;gt; {{---}} функция возвращающая число Стирлинга второго рода для заданных аргументов. &amp;lt;/font&amp;gt;&lt;br /&gt;
     r = random(1, s)&lt;br /&gt;
      '''if''' stirling(n - l - 1, k - m - 1) &amp;gt;= r&lt;br /&gt;
        result[i] = k - m &amp;lt;font color = green&amp;gt; // &amp;lt;tex&amp;gt; result[i] &amp;lt;/tex&amp;gt; {{---}} номер подмножества в котором находится элемент &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. &amp;lt;/font&amp;gt;&lt;br /&gt;
        l = l + 1&lt;br /&gt;
        m = m + 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
        p = random(1, k - m) &amp;lt;font color = green&amp;gt; // Случайным образом выбираем номер одного из незаконченных подмножеств. &amp;lt;/font&amp;gt;&lt;br /&gt;
        result[i] = p&lt;br /&gt;
        l = l + 1&lt;br /&gt;
   '''return''' result&lt;br /&gt;
&lt;br /&gt;
Так как на каждом шаге интервал случайных чисел разделяется только на на два диапазона, а всего шагов {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; то итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt; O(n) + O(n^2) &amp;lt;/tex&amp;gt; на преподсчет чисел Стирлинга второго рода (если преподсчитать их динамически).&lt;br /&gt;
&lt;br /&gt;
=== Разбиение на случайное число подмножеств ===&lt;br /&gt;
Описаный алгоритм можно применить для получения разбиения множества на случайное число подмножеств. Для этого достаточно случайным образом выбрать число подмножеств из интевала &amp;lt;tex&amp;gt; [1, n] &amp;lt;/tex&amp;gt; , так чтобы вероятность получить число &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; была пропорциональна числу способов разбить &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; элементов на &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; подмножеств (что равно &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt;\lbrace{n\atop k}\rbrace&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Разделим интервал случайных чисел &amp;lt;tex&amp;gt; [1, s] &amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt; s = &amp;lt;/tex&amp;gt; &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt; \sum_{i=1}^n \left\{{n\atop i}\right\}&amp;lt;/tex&amp;gt;) на &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; диапазонов, так чтобы размер диапазона &amp;lt;tex&amp;gt; d_i &amp;lt;/tex&amp;gt; был равен &amp;lt;tex dpi = &amp;quot;180&amp;quot;&amp;gt; \lbrace{n\atop i}\rbrace &amp;lt;/tex&amp;gt;. С помощью функции для генерации случайного числа получим число &amp;lt;tex&amp;gt; r &amp;lt;/tex&amp;gt; в интервале &amp;lt;tex&amp;gt; [1, s] &amp;lt;/tex&amp;gt; и выберем количество подмножеств &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; соответствующее диапазону отрезка в которм находится полученное число и по выбранному &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; получим случайное разбиение множества размера &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; подмножеств.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[Метод генерации случайной перестановки, алгоритм Фишера-Йетса|Метод генерации случайной перестановки]]&lt;br /&gt;
*[[Методы генерации случайного сочетания|Методы генерации случайного сочетания]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*Комбинаторные алгоритмы: учебное пособие / Т. И. Федоряева. - Новосибирск: Новосибирский гос. ун-т, 2011. 118 с. - ISBN 978-5-4437-0019-9&lt;br /&gt;
*Non-Uniform Random Variate Generation / Luc Devroye. - Springer, New York, NY, 1986. 843 c. - ISBN 978-1-4613-8645-2&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Комбинаторика]]&lt;/div&gt;</summary>
		<author><name>217.66.157.236</name></author>	</entry>

	</feed>