Разложение числа на слагаемые
Этот онлайн калькулятор выводит все представления числа n в виде суммы положительных целых чисел.
Данный онлайн калькулятор для введенного числа в диапазоне от 1 до 60 выводит все его представления в виде суммы положительных целых чисел, а также выводит количество таких представлений.
В математике представление числа в виде суммы положительных целых чисел называется разбиением натурального числа n, при этом в канонической записи разбиения слагаемые перечисляются в невозрастающем порядке. Описание алгоритма генерации всех разбиений можно найти под калькулятором.
Разбиение натурального числа
Задача разложения числа на слагаемые
В большинстве источников, которые можно легко найти поиском, приводится рекурсивный алгоритм разложения числа на слагаемые. В данном же калькуляторе, в силу технических причин, используется итеративный алгоритм. Логика алгоритма была взята из статьи на Хабре.
Так как логика алгоритма достаточно лаконичная, приведу ее целиком (с некоторыми комментариями):
Дано: исходный массив в виде единиц — А (1,1,1,1,1).
Размерность массива соответствует числу n, все разложения которого мы ищем.
0) Если получили сумму, тогда остановка алгоритма.
Как и автор статьи, я суммирую элементы в массиве, в конце должен остаться только один элемент с индексом 0, численно равный n.
1) Двигаясь по массиву слева направо, искать в массиве А первый минимальный элемент — x,
последний элемент не учитывается (не участвует в поиске минимального).
Нам нужно как значение элемента, так и его позиция в массиве. Поэтому я не пользуюсь встроенными в Javascript функциями типа min и findIndexOf, а использую одну итерацию по массиву, запоминая как текущий минимальный элемент, так и его позицию, а также сумму до текущего минимального элемента включительно (сумма понадобится ниже).
2) Перенести единицу из конца (последнего элемента) в найденный минимальный элемент x
(равносильно увеличению x на единицу и уменьшению на единицу последнего элемента).
Здесь прибавляется единица, и используется метод splice
3) Разложить сумму всех элементов после измененного элемента — x – на единицы.
Здесь добавляем единицы, используя ранее подсчитанную частичную сумму.
Код алгоритма на Javascript приведен ниже (разбиения выводятся в консоль):
Остается добавить, что, как и в любой другой комбинаторной задаче, число разбиений экспоненциально зависит от числа n. Если для 10 это 42, то для 50 это уже 204 226, а для 100 — 190 569 292. В данном калькуляторе установлено ограничение в 60, что дает 966 467 разложений и считается на моем ноутбуке примерно 12 секунд. При 100 у браузера заканчивалась память и он падал.
Зависимость числа разбиений от n является числовой последовательностью A000041 в онлайн энциклопедии целочисленных последовательностей и обладает рядом некоторых интересных свойств.
Как разложить число на слагаемые
Найдите число p(n) разложений числа n на слагаемые (повторения разрешены, порядок не важен).
Например, для n = 5 число разложений равно 7, а для n = 6 число разложений равно 11:
Начальные значения:
| n | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| p(n) | 1 | 2 | 3 | 5 | 7 | 11 | . |
Обратите внимание на выбраную систему выписывания всех разложений. Слагаемые записываются в порядке невозрастания.
Посмотрим на разложения 6, которые начинаются на 2. После слагаемого 2 нужно записать разложения 4, в которых слагаемые не превосходят 2.
Параметризация: P(n,k) — число разложений числа n на слагаемые (повторения разрешены, порядок не важен), которые не превосходят k.
Множество всех таких разложений разбивается на две группы — те, которые содержат слагаемое k и те, которые не содержат.
Число последних равно P(n, k-1).
Рассмотрим те, которые содержат слагаемое k. Они выглядят как n = k + . Вместо троеточия может идти любое разложение числа n — k на слагаемые, которые меньше либо равны k. Их количество равно P(n-k, k).
Нерекурсивный алгоритм генерации всех разбиений и композиций целого числа
Привет, Хабр! Вдруг снова захотелось написать сюда! Так как было время на выходных, я снова решил поиграться с алгоритмизацией и написал вот эту статейку. Хотел даже отправить в какой-нибудь рецензируемый журнал, но оценить тривиальность/нетривиальность данного материала я не в состоянии, так как программирование всего лишь мое хобби и то эпизодическое, поэтому, как обычно, заранее прошу прощения, если все окажется слишком простым и до боли знакомым.
Спасибо администрации Хабра за отзывчивость и молниеносную оперативность при восстановлении аккаунта!
Итак, плоды усилий долгих.
Нерекурсивный алгоритм генерации всех разбиений целого числа в лексикографическом
порядке, когда все элементы выстроены в порядке убывания, является альтернативным; в
Интернете представлено несколько способов порождения данных комбинаторных
объектов, однако, как это справедливо и относительно других комбинаторных алгоритмов,
реализации сводятся к двум типам — нерекурсивному и рекурсивному. Чаще можно встретить
реализации, которые не учитывают порядок вывода объектов или осуществляют
вывод по принципу дробления числа.
Приведенная ниже реализация работает по обратному принципу: исходное число изначально разбито на единицы, алгоритм работает до тех пор, пока число в нулевом индексе массива не станет равным сумме исходного числа. Особенностью данного алгоритма является то, что он крайне прост для понимания, однако это не лишает его некоторый специфики:
1) Первый объект просто выводится на экран в самом начале, таким образом, он вынесен за пределы циклов, фактически является инициализирующим;
2) Существует несколько способов реализации переноса единицы, которые могут, как упростить код, так и сделать его более запутанным;
3) Данная нерекурсивная реализация может служить наглядным примером для объяснения генерации комбинаторных объектов на нескольких процессорах, после незначительной модификации. Для разделения генерации на процессоры достаточно: а) определить элемент по его номеру и сделать инициализирующим; б) определить момент для остановки работы. Например, если известно число объектов, генерируемых на одном процессоре, то достаточно ввести еще одну инкрементируемую переменную в верхний цикл и изменить условие выхода из самого верхнего цикла по достижении требуемого количества.
Код на языке PHP приведен только для демонстрации корректности алгоритма и может содержать лишние языковые средства, которые добавляют реализации избыточности.
Описание алгоритма
Дано: исходный массив в виде единиц — А (1,1,1,1,1).
Шаги
0) Если получили сумму (в случае реализации ниже, если нулевой индекс равен сумме числа), тогда остановка алгоритма.
1) Двигаясь по массиву слева направо, искать в массиве А первый минимальный элемент — x,
последний элемент не учитывается (не участвует в поиске минимального).
2) Перенести единицу из конца (последнего элемента) в найденный минимальный элемент x
(равносильно увеличению x на единицу и уменьшению на единицу последнего элемента). 3) Если в массиве А есть ноль — 0, то удалить последний элемент.
4) Разложить сумму всех элементов после измененного элемента — x – на единицы.
Update:
Операция с поиском и удалением 0 в массиве лишняя (так как используется array_splice, а затем новое заполнение массива), как правильно было замечено в комментарии участником dev26
Хотел бы в конце поделиться одним наблюдением, я очень долго пытался понять, почему одни алгоритмы понятны сразу и легки для кодирования, а другие заставляют мучиться… и мучиться порой долго. Должен отметить, что этот алгоритм у меня получилось закодировать почти сразу, но только после того, как я получил однозначно понятное описание каждого шага. И тут есть важный момент, понять алгоритм и описать — задачи одна другой не легче. Однако, в алгоритмизации и составлении описания, особенно важным оказывается то, какими глаголами описываются действия в алгоритме — это (субъективно) в конечном счете может влиять и на конечную реализацию.
Литература
[1] Donald E. Knuth. The Art of Programming. Vol. 4. 2008.
[2] Dennis Ritchie and Brian Kernighan. The C Programming Language. 1978.
[3] Aleksandr Shen. Algorithms and Programming: Problems and Solutions.
[4] ru.wikipedia.org/wiki/Разбиение_числа
[5] en.wikipedia.org/wiki/De_Arte_Combinatoria
P.S. Несмотря на приведенный список литературы, алгоритм пришлось выводить заново.
Еще одно дополнение:
Вынос первого элемента из циклов при данном подходе имеет силу как для генерации разбиений, так и для генерации сочетаний, перестановок. В принципе данный подход (хоть и несколько избыточный при реализациях) вполне обобщается для генерации других комбинаторных объектов.
UPDATE
Алгоритм разбиений в соединении с алгоритмом перестановок позволяет генерировать и все композиции числа. Идея простая: для каждого разбиения вызывается функция генерации всех перестановок для этого разбиения.
Разрядные слагаемые — правило и примеры разложения чисел
Натуральными называют естественные величины, которые используются для счета (цифры и их комбинации: 1, 2, 3, 4, 5 и так далее), а также для расстановки по очереди (порядковые числительные: первый, второй, третий, четвертый и так далее). В совокупности они образуют так называемый ряд натуральных чисел. Его обозначением служит латинская буква N.
Главной особенностью этого ряда считается его бесконечность. Она обусловлена тем, что самого большого числа не существует. У любой составляющей ряда есть «старшие товарищи» — величины, которые по своему значению больше.

Распределение по категориям
Составляющие ряда натуральных чисел подразделяются на разряды и классы. Каждая из этих категорий неразрывно связана с другими. Разрядная классификация состоит из следующих групп (в скобках приведены слагаемые, соответствующие каждому разряду):
- единицы (1, 2, …, 9);
- десятки (10, 20, …, 90);
- сотни (100, 200, …, 900);
- тысячи (1000, 2000, …, 9000) и так далее.
Разряд числа — это положение, которое оно занимает в цифровой записи. Таким образом, любое числовое значение можно представить посредством разрядных слагаемых по математической формуле следующего вида: nnnn = n000 + n00 + n0 + n, где n означает любую цифру от 0 до 9. Для наглядного примера стоит разбить на составляющие число 4698 = 4000 + 600 + 90 + 8. Получается, что оно состоит из четырех разрядов, отображенных соответствующими составляющими:

- 4000 (четыре тысячи) — это первое слагаемое;
- 600 (шесть сотен) — второе;
- 90 (девять десятков) — третье;
- 8 (восемь простых единиц) — четвертое.
Разряд первого слагаемого называют высшим. Цифра, которой он обозначается, всегда больше нуля. Количество разрядов числа, как и количество его разрядных составляющих, всегда соответствует количеству в нем цифр, отличных от 0. Например, число 7052 состоит из трех разрядов, несмотря на свою четырехзначность. Это связано с тем, что в его составе отсутствуют сотни. Его слагаемые — семь тысяч, пять десятков и две простых единицы (7000 + 50 + 2 = 7052).
Разрядные составляющие — это натуральные числа, содержащие только одну цифру, отличную от нуля. Примеры разрядных слагаемых: 7, 30, 200, 4000 и тому подобные. Числа такого вида, как 12, 21, 475, 3500 и так далее, не могут быть отнесены к этой категории. Они подлежат математическому разложению на составляющие.
Название разрядных слагаемых обусловлено принадлежностью каждого из них к определенному разряду. Тысяча считается единицей четвертого разряда, сотня — единицей третьего разряда, десяток — второго, единица — первого. То есть нумерация разрядов начинается от наименьшей составляющей. Единицы первого разряда называются простыми, так как они однозначные. Составляющие прочих разрядов относятся к составным.
Каждый разряд состоит из десяти единиц, но обозначаться он может только девятью, так как десятая единица обеспечивает переход на следующий более высокий разряд. Не может быть разрядной составляющей типа десяти сотен — эта единица обозначается как одна тысяча.
Комплектация разрядов
В целях упрощения записи представления числа через разрядные составляющие единицы разрядов принято группировать в классы. В состав каждого из них входит три разряда:
- единицы;
- десятки;
- сотни.

Для удобства между классами разрешается ставить пробел. Особенно это необходимо для представлений очень больших величин (от миллиона), чтобы они не выглядели бесконечным набором цифр, и в процессе их разложения не возникло путаницы. На классы число разбивается строго по три цифры справа налево.
Первый класс — это единицы. Он включает от одного до трех разрядов. Это значит, что к нему относятся все натуральные числа от 1 до 999. Второй класс — это тысячи. В него входят от четырех до шести разрядов. То есть единицы, принадлежащие к этому классу, есть во всех величинах от 1000 и больше. Дальнейшее распределение по классам:
- третий — миллионы (с седьмого по девятый разряды);
- четвертый — миллиарды (с десятого по двенадцатый);
- пятый — триллионы (с тринадцатого по пятнадцатый);
- шестой — квадриллионы (с шестнадцатого по восемнадцатый);
- седьмой — квинтиллионы (с девятнадцатого по двадцать первый) и так далее.
Распределение по классовым и разрядным категориям отображено в таблице:
- сотни млрд;
- десятки млрд;
- млрд;
- сотни млн;
- десятки млн;
- млн;
- сотни тысяч;
- десятки тысяч;
- тысячи;
- сотни;
- десятки;
- единицы.
Особенности разложения
Чтобы лучше понять, что такое разрядные слагаемые в математике и как их использовать, стоит подробно рассмотреть процесс разложения натуральных величин на эти составляющие. В основе большинства задач с разрядными слагаемыми лежит разложение натурального числа, то есть его представление в виде суммы разрядов через сложение количеств всех разрядных единиц.
Преобразить в сумму разрядных слагаемых можно каждую натуральную величину составного типа, то есть многозначную (двузначную, трехзначную и так далее). Чтобы разложить число на разрядные слагаемые корректно, необходимо соблюдать основные правила. Первое — нули не учитываются в разрядном составе числа. Второе — слагаемые записываются в порядке старшинства, то есть от старшего к младшему — вначале тысячи, затем сотни и десятки, последними фиксируются простые единицы.
Разрядный состав можно записать в трех вариантах разбора:
- базовый — простое сложение: 852768 = 800 000 + 50 000 + 2000 + 700 + 60 + 8;
- подробный — сложение с умножением единиц разряда на их количество: 852768 = 8*100 000 + 5*10 000 + 2*1000 + 7*100 + 6*10 + 8*1.
- словесный — текстовая расшифровка: 852768 = восемь сотен тысяч, пять десятков тысяч, две тысячи, семь сотен, шесть десятков, восемь простых единиц.
Вне зависимости от выбранного способа разложить число на составляющие по разрядам не составит особого труда. Конечно, чем больше число, тем выше риск запутаться и совершить ошибку. Упражняться лучше сперва на двузначных числах, а затем постепенно повышать разрядность.

Упражнения для тренировки
Для лучшего усвоения материала стоит разобрать несколько тренировочных упражнений. Несколько примеров, какими бывают математические задания по этой теме:
- 75 = 70 + 5;
- 324 = 300 + 20 + 4;
- 8434 = 8000 + 400 + 30 + 4;
- 68 486 = 60 000 + 8000 + 400 + 80 + 6;
- 575 783 = 500 000 + 70 000 + 5000 + 700 + 80 + 3;
- 8 633 087 = 8 000 000 + 600 000 + 30 000 + 3000 + 80 + 7.
Нередки упражнения с обратным процессом, то есть такие, в которых нужно найти число по его составляющим:

- 500 + 60 + 5 = 565;
- 8000 + 300 + 4 = 8304;
- 900 000 + 50 000 + 7000 + 80 + 2 = 957 082.
Стоит отметить, что не все задачи с разрядными составляющими решаются путем сложения. Многие упражнения содержат прием их вычитания. Но сложными такие задания кажутся только на первый взгляд. Их суть проста. В скобках приводятся составляющие двух чисел — уменьшаемого и вычитаемого. Требуется найти их разность: (500 + 40 + 1) — (400 + 20) = (100 + 20 + 1) = 121.
Процессы разложения чисел по разрядам и обратного сложения имеют огромное значение для решения различных математических задач и упражнений. Очень важно уметь быстро раскладывать числа любой величины по разрядному составу. Это умение поможет в устном счете и оперировании многозначными числами.
Изучение натуральных чисел и разрядного состава входит в базовую программу по математике. Этот материал проходится учащимися в начальных классах школы.