Как посчитать количество счастливых билетов
Счастливые билетики до 300 цифр
Началось все с тестового задания на вакансию «js-developer, Node.js-developer», и тут я выпал в осадок: задача на счастливые билетики.
Посчитать количество счастливых билетиков для 2, 4, 6, 8 и 10 цифрового значения.
Уверен, многие уже не раз делали эту банальную задачку, но, как правило, для 6-ти цифр (для тех, кто не понимает о чем пойдет речь).
Банальное решение:
Также можно посмотреть тут.
А если цифр 10? 30? 200? Беда! Приходиться ооочень долго ждать результата: аналог в PHP (5.3) «умирал», даже когда я давал 10 цифр и set_time_limit (3600).
Теперь вернемся в мир JS. Несмотря на то, что простые циклы в Node.js выполняются быстрей, чем в PHP, время выполнения меня все равно не устраивало (1 029 458 ms).
А теперь хватит этого унылого текста, переходим к альтернативному решению.
Сама зацепка оказалась в журнале «Квант», № 12 (1976), с.68–70 (электронный вариант ).
Там же можно увидеть вывод — таблица, с помощью которой можно легко узнать «количество счастья» в билетах из 2 (n=1), 4 (n=2), 6 (n=3) и 8 (n=4) цифрами.
Как заполнить таблицу — изображено ниже:
Ну и проверить же нужно:
Собственно то, к чему все велось: время выполнения 106 ms (. ), страшно представить, что бы случилось при использовании банального способа.
Счастливобилетчикам — по носу математикой
Искать счастье бесполезно, главное — где оно найдет тебя. Некоторые, в том числе и я, заимел привычку проверять маршрутные проездные билеты на предмет этого «счастья» — билет можно назвать «счастливым», если сумма его первых трех цифр равняется сумме трех остальных. Забавное такое, знаете ли, занятие.
Но иногда бывает так, что счастливые билеты попадаются очень часто, а иногда — их не бывает и несколько месяцев. Это если ездить один раз в день по какому-нибудь маршруту.
И тут приходит замечательный вопрос: «сколько всего существует счастливых билетов?», а еще лучше, когда приходит математика с ее не менее красивым вопросом: «какова вероятность покупки счастливого билета?»
Для человека, который постиг азы программирования, не составит большого труда написать программу для подсчета этого самого количества счастливых билетов — обычным методом перебора. Что сделал и я, получив результат — 55 251 билет, который говорит, что примерно каждый восемнадцатый билет будет счастливым.
Но теперь представьте себе образ кондуктора — человека-сумка-через шею, с несколькими килограммами мелочи и катушкой билетов, которые он выдает последовательно за определенную плату. И что будет, если вы станете счастливым обладателем билета с номером «010100»? Правильно, счастливобилетчиков на этом маршруте не будет, пока кондуктор не покончит с этой катушкой.
Теперь попробуем ответить на этот вопрос математически.
Максимально возможно счастливый билет «999999» имеет сумму триад равную 27 = 9+9+9 = 9+9+9. Билетов с суммой счастливых цифр равной 1 будет 9, это билеты:
001001 010001 100001
001010 010010 100010
001100 010100 100100
Билетов с суммой счастливых цифр равной 3 будет 36. Можете посчитать сами — любым методом. Составим таблицу для каждой такой комбинации:
Сумма триад / Количество счастливых билетов в группе
1 / 9
2 / 36
3 / 100
4 / 225
5 / 441
6 / 784
7 / 1296
8 / 2025
9 / 3025
10 / 3969
11 / 4761
12 / 5329
13 / 5625
14 / 5625
15 / 5329
16 / 4761
17 / 3969
18 / 3025
19 / 2025
20 / 1296
21 / 784
22 / 441
23 / 225
24 / 100
25 / 36
26 / 9
27 / 1
Сумма: 55251
Получается, что максимальное количество счастливых билетов будет в группах, сумма триад которых равняется 13 или 14.
В таких катушках каждый девятый билет будет счастливым, пока сумма двух цифр одной триады не превзойдет значения 13…14. Следовательно, можно логически предположить, что каждый 18 билет в такой группе будет счастливым. А ввиду такого «классического» распределения, то и во всей группе билетов от 000001 до 999999.
Осталось вспомнить один из методов теории вероятностей, и посчитать:
Получая результат с хорошей точностью, с отклонением ≈ 3%.
А еще, счастливые билеты нужно съедать, чтобы ощутить этот прилив вселенского счастья.
Подсчитать общее количество «счастливых» билетов
Подсчитать количество «счастливых» шестизначных билетов в рулоне и вывести их номера на экран
Напишите программу, которая подсчитывает количество «счастливых» билетов в рулоне и выводит их.
Определить количество счастливых билетов
Имеется часть катушки с автобусными билетами. Номер билета 6-ти значный. Составить программу.
и как сделать?изменить начало отсчета только?
Добавлено через 35 минут
как ж все же сделать?
Вот чуть более хитрый алгоритм. В нем в 1000 раз меньше итераций (впрочем, этого можно и в предложенных алгоритмах достигнуть). Но такой алгоритм вроде по проще будет:
Комментарий модератора | ||
Если у вас есть дополнение к уже созданной теме, найдите эту свою тему и сделайте это дополнение. |
Добавлено через 13 минут
В 12 студии чуть по другому, нужно сделать правый клик по проекту, выбрать Add Reference(добавить ссылку), и уже там искать System.Numerics.
Переведенный за две минуты вариант для шарпа без проверок на входные данные и прочих наворотов:
Найти количество всевозможных шестизначных счастливых билетов
Найти количество всевозможных шестизначных счастливых билетов (для простого алгоритма потребуется.
Найти количество счастливых билетов с шестизначными номерами
Построить алгоритм для нахождения количества счастливых билетов с шестизначными номерами. Билет.
Составить программу, определяющую количество счастливых билетов на катушке
6.3.2. Помогите, пожалуйста, решить задачу в С++ с помощью функций. Имеется часть катушки с.
Найти количество счастливых билетов учитывая скорость выполнения программы
Найти количество счастливых билетов учитывая скорость выполнения программы,счастливый билет имеет.
Как посчитать количество счастливых билетов
Счастье за деньги не купишь, гласит народная мудрость. Зато можно, хоть и случайно, купить счастливый билетик. Мы воспринимаем это событие как удачу, потому что оцениваем его вероятность как низкую. Но так ли уж редко это происходит на самом деле?
Эта статья была опубликована в журнале OYLA №9(37). Оформить подписку на печатную и онлайн-версию можно здесь.
Сперва проясним, что такое счастливый билет. Любой билет, в кино или на поезд, имеет уникальный номер. Как правило, его присваивают последовательно начиная с 0 и до некоторого значения. Делается это для удобства учёта. Мы будем рассматривать билеты, у которых номер состоит из 6 цифр: от 000000 до 999999. Определений счастливого билета несколько, но мы остановимся на наиболее популярном: билет называется счастливым, если сумма первых трёх цифр его номера равна сумме последних трёх цифр. Прежде чем начать охоту за билетами, давайте ответим на частые вопросы, с ними связанные. В этом нам поможет математика.
Переведём этот вопрос на формальный язык математики: существует ли такой счастливый билет ABCDEF, что ABCDEF + 1 тоже будет счастливым? Иначе говоря, для этих чисел должно выполняться равенство:
A + B + C = D + E + F
A + B + C = D + E + F + 1
Если первое из шестизначных чисел оканчивается не на 9 (F9), то при прибавлении единицы сумма последних трёх цифр изменится, а первых трёх нет, значит, билет перестанет быть счастливым. Если же на конце было 9 (F = 9), то сумма последних трёх цифр уменьшится (если на конце более трёх девяток, то уменьшится и сумма первых трёх, но не настолько). Итак, счастливые билеты подряд не идут. Но, с другой стороны, подряд они могут идти через девятку: например, 100001 и 100010. Более того, иногда цепочка «через девять» бывает весьма длинной: 900009, 900018, 900027, …, 900090. Это если нам повезло с началом. А если начало — 998999? Тогда ближайший счастливый билет будет аж через тысячу! Действительно, дальше все билеты будут начинаться с 999, так что на конце для счастья тоже надо иметь 999…
Для начала попробуем приблизительно оценить их количество. Несложная оценка снизу: нам подходят все билеты вида АВСАВС. Сколько таких билетов? А столько же, сколько всего комбинаций первых трёх цифр — 1000. Так что счастливых билетов точно не меньше 1000. Неплохо, но мы не учли кучу вариантов, когда цифры разные — например, те же 900018. Можно попытаться учесть перестановки цифр АВС, то есть билеты вида АВСВСА, АВСАСВ и т. д. Но, увы, просто умножить на 6 (количество возможных перестановок цифр А, В и С) не получится: если среди них есть совпадающие цифры, то мы имеем уже не 6 вариантов, а 3 или 1.
Впрочем, эту идею можно реализовать по-другому. Рассмотрим все комбинации следующего вида: на первых трёх местах стоят цифры А, В и С, на вторых трёх — те же цифры, но в произвольном порядке. Сколько же таких вариантов набежит? На первом месте может стоять любая из 10 цифр, то есть пока 10 вариантов. Для любой первой цифры есть 9 вариантов второй, значит, их уже 90. Для каждого из этих 90 существует 8 вариантов третьей цифры — всего, стало быть, 720. И теперь нам осталось умножить 720 на количество способов переставить три фиксированные различные цифры по оставшимся трём местам. Как мы уже поняли, таких вариантов 6, значит, общее количество чисел — 4320. Однако и это оценка снизу, причём «сильно снизу»: мы всё ещё не учитываем варианты с разными цифрами.
Хорошо, попробуем теперь оценить искомую сумму сверху. Заметим, что, если каждый счастливый билет ABCDEF заменить на билет ADBECF, количество не изменится, значит, можно просто посчитать количество шестизначных чисел, у которых сумма цифр на чётных местах равна сумме на нечётных. А это очень похоже на признак делимости на 11! Напомним, если в числе разность между суммой цифр на чётных и нечётных местах делится на 11, то и число делится на 11. Значит, все наши счастливые билеты «второго типа» делятся на 11, а тогда их не больше, чем чисел, делящихся на 11, то есть 90909 (1000000 : 11). Получается, что счастливых билетов не больше 90909. Впрочем, это также очень грубая оценка, ведь вовсе не каждое число, делящееся на 11, имеет равные суммы цифр на чётных и нечётных местах — например, 000506. Так что счастливых билетов существенно меньше. Давайте же точно подсчитаем, сколько их!
Чтобы посчитать точное количество, заменим каждую из трёх последних цифр на дополняющую её до 9. D заменим на K = (9 – D), E на M = (9 – E), F на N = (9 – F). Так как исходно A + B + C = D + E + F, то теперь для числа ABCKMN:
A + B + C + K + M + N
A + B + C + 9 – D + 9 –E + 9 – F
Итак, количество счастливых билетов в точности равно количеству чисел от 000000 до 999999, сумма цифр которых равна 27. Стало немного легче, но предстоит ещё немало работы. Сперва вычислим искомое количество. Для этого нарисуем таблицу, в которой по горизонтали укажем количество используемых цифр, а по вертикали — искомую сумму. Таким образом мы последовательно ответим на все вопросы вида «Сколько существует способов представить число k в виде суммы n цифр». Делать это мы будем рекурсивно, то есть выражать большие значения через меньшие. Поехали!
Очевидно, что в первом столбце у нас будет по одному способу получить числа от 0 до 9 (с помощью одной цифры), а всё, что больше 9, — 0 способов.
Далее, если перейти ко второму столбцу и взять, допустим, число на пересечении второго столбца и шестой строки (k = 5), сколько существует способов представить 5 в виде суммы двух цифр? Логика тут простая. В качестве второй цифры мы можем выбрать любой из вариантов от 0 до 5. Если выбираем 0, то сумма всех цифр, кроме второй, должна быть равна 5 (да-да, понятно, что в данном случае «всех, кроме второй» — это только первая цифра, но давайте сразу составим алгоритм в общем виде). Если выбираем в качестве второй цифры 1, то сумма оставшихся должна быть равна 4 и т. д. Но ведь тогда мы просто должны сложить способы из предыдущего столбца — для всех чисел от 0 до 5! И получить 6 вариантов.
Ещё пример: допустим, я хочу заполнить во втором столбце поле для k = 11. Несложно увидеть, что тогда вторая цифра 0 или 1 не даёт ни одного варианта, так как первая не может быть больше 9. Иначе говоря, мы обращаемся к пустым ячейкам первого столбца, которые соответствуют k = 10 и k = 11. Впрочем, можно считать, что там не пустота, а нули — это не важно. Так или иначе, мы должны сложить все варианты из предыдущего столбца, от k = 2 до k = 11. Это даёт 8. Таким же образом заполняем второй столбец. Последнее число мы впишем при k = 18, так как максимальная сумма двух цифр равна 18.
Переходим к третьему столбцу. Давайте ещё раз посмотрим на примере, как он заполняется. Допустим, k = 15. Тогда, поскольку последняя цифра может быть от 0 до 9, сумма первых двух должна быть равна 6, 7, 8, 9, …, 15. А для всех этих чисел мы уже знаем количество способов представить их в виде суммы двух цифр. Берём эти значения из таблички (это числа 7, 8, 9, 10, 9, 8, 7, 6, 5 и 4), складываем их и получаем результат: 73 способа представить 15 в виде суммы трёх цифр.
Действуя аналогично, продолжаем заполнять табличку. Занятие это весьма муторное, но конечное. Особенно если написать программу. Но можно сделать всё и руками — главное, нигде не обсчитаться. И если довести таблицу до шестого столбца, число, соответствующее k = 27, и будет искомым ответом. Если вы не ошибётесь, то получите ровно 55 252.
Альтернативный подход
Прежде чем делать выводы, попробуем подсчитать количество счастливых билетов другим способом. Например, так: ограничимся в предыдущем решении первыми тремя столбцами. В третьем мы получили количество способов представить число k в виде суммы трёх цифр — мы сделали это для любого k от 0 до 27. Теперь забудем наши соображения о девятках (про замену цифр на дополняющие до 9) и рассмотрим произвольный счастливый билет ABCDEF. Пусть A + B + C = k. Сколько есть способов подобрать такие А, В и С? Это мы знаем из таблички — допустим, D3(k).
А сколько способов подобрать вторые три цифры? Да столько же, ведь речь всё о тех же вариантах представить число k как сумму трёх слагаемых! Стало быть, так как нас устраивают любые комбинации, общее количество способов подобрать счастливый билетик, у которого сумма первых трёх цифр равна k, будет (D3k2). Следовательно, всё, что осталось сделать, — это взять числа из третьего столбца (1, 3, 6, 10, …, 1), каждое из них возвести в квадрат и полученные квадраты сложить. Если всё это проделать, получится то же число 55 252.
Да, есть и более короткая комбинаторная формула, но вывести её гораздо сложнее. Не будем приводить полное рассуждение — лишь обозначим идею и выпишем окончательную формулу. Идея в следующем: вернёмся к тому, что нам надо посчитать количество способов представить 27 как сумму 6 цифр. Сделаем это так: возьмём 27 яблок и поставим среди них 5 перегородок. Тогда количество яблок до первой перегородки будет первым слагаемым суммы, от первой перегородки до второй — вторым слагаемым и т. д. Обратите внимание, что перегородки могут стоять подряд, и в этом случае слагаемое окажется равным нулю. Значит, задача сводится к подсчёту количества способов расставить перегородки. Но заметим, что всего у нас получилось 32 объекта (27 яблок и 5 перегородок) и мы должны выбрать местоположение для 5 перегородок (на остальные места встанут яблоки). Сколько же существует способов выбрать 5 мест из 32? C32, если вы знакомы с комбинаторикой (впрочем, если не знакомы — столько же).
Проблема в том, что это ещё не ответ. Мы посчитали количество способов представить 27 в виде суммы 6 слагаемых, но пока не учли, что ни одно слагаемое не должно быть больше 9. Если же учесть это, итоговая формула будет такой:
Это число посчитать гораздо проще, и мы тоже получим 55 252 — можете убедиться сами.
Итак, что же мы получили? Мы вычислили, что примерно 5,5% билетов являются счастливыми, — иначе говоря, в среднем каждый восемнадцатый. Не так уж и редко, оказывается!
А вот оправдается ли статистика на практике, проверяйте сами. И помните, что если съесть такой билетик раньше времени, то кроме отравления можно заработать ещё и немаленький штраф от контролёра, что мало соответствует представлениям большинства о счастье. Зато счастье от решения непростой задачи у нас никто не отнимет. До новых счастливых встреч!
Зона кода
Как стать счастливым? Неоднократно, устами умнейших своих представителей, человечество пыталось дать ответ на этот вопрос.
Один из ответов (не ручаемся за то, что его автор относится к указанной группе) гласит: для счастья нужно совсем немного: всего-то — купить у кондуктора трамвайный билетик со счастливым номером. Далее нужно произвести определённые действия. Какие именно — я, признаться, уже плохо помню. Вроде, речь шла даже о том, что билетик нужно съесть.
Мы ни в коем случае не предлагаем запихивать в рот, а уж, тем более, пропускать через желудочно-кишечный тракт не очень чистую бумагу, покрытую типографской краской и предупреждаем, что подобные действия могут негативно отразиться на вашем здоровье. И вообще, на вопрос, поставленный в начале статьи, у нас ответа нет.
Интересовать нас будет ответ на другой вопрос, гораздо менее глобальный. Детально сформулируем его в виде следующей задачи.
Каждый трамвайный билет имеет номер, состоящий из шести произвольных цифр от 0 до 9. Номер считается «счастливым», если сумма его первых трёх цифр совпадает с суммой трёх последних. Например, счастливым является номер «123420». Сколько всего существует счастливых номеров?
В дальнейшем билет со счастливым номером тоже будем называть счастливым. Задачу будем решать различными способами. Программы будут весьма простыми, поэтому данную статью можно смело рекомендовать новичкам в программировании на C99 (именно этот язык будет использоваться в статье). Правда, «математическая» часть статьи может показаться сложной тем, кто с комбинаторикой пока на «Вы».
Метод перебора
Первый способ, который мы будем использовать — «лобовой». Разумеется, речь идёт о методе перебора. «Лобовые» способы обычно имеют ряд преимуществ перед более изощрёнными. Они, как правило, более просты с точки зрения разработки и реализации. Как следствие, на их создание тратится меньшее время. Наконец, в их реализации сложнее допустить ошибку.
Так что, если никаких особых требований к решению задачи не предъявляется (например, связанных с объёмом памяти, быстродействием, количеством операций), то «лобовой» метод вполне сгодится. Но, конечно же, программа, построенная даже на таком методе, должна, как минимум, запускаться на компьютере (неожиданно, не правда ли?) и, кроме этого, выполняться приемлемое время.
Современные (и даже не очень) компьютеры выполняют перебор миллиона чисел (а именно столько существует номеров билетов) за доли секунды, поэтому проблем с временем выполнения явно не возникнет.
Идея метода перебора заключается в следующем. Будет создана переменная для хранения текущего числа обнаруженных счастливых номеров. Для перебора всех возможных номеров будем использовать два цикла: внешний и внутренний. Счётчик каждого из них будет пробегать значения от 0 до 999. Таким образом, можно считать, что счётчик внешнего цикла содержит первую «тройку» цифр номера, а счётчик внутреннего — вторую (или наоборот).
На каждой итерации внутреннего цикла будут сравниваться суммы цифр значений счётчиков циклов; в случае их равенства значение счётчика счастливых номеров будет увеличиваться на единицу. По окончании итераций значение счётчика счастливых номеров будет выведено на печать.
Для подсчёта упомянутых сумм цифр нам нужно научиться извлекать из любого числа от 0 до 999 цифры, которые используются для его записи. Договоримся считать, что количество цифр всегда равно трём, даже если число двухзначное или однозначное (в этом случае «недостающие» цифры будем считать нулями).
Эти цифры получить несложно. Первую цифру можно получить, если произвести целочисленное деление числа на 100. Вторую — если целую часть частного от деления числа на 10 снова разделить на 10 и взять остаток. Наконец, третью — если разделить число на 10 и взять остаток.
Ниже приведён код программы, решающей нашу задачу методом перебора.
Выполнение программы приводит к следующему выводу на консоль:
Задача методом перебора решена.
Альтернативный способ
Напишем теперь более эффективную программу. Разницы в быстродействии мы, скорее всего не увидим, но зато, надеюсь, получим моральное удовлетворение от проделанной работы. Действовать будем следующим образом.
Очевидно, что если записать подряд два любых числа из диапазона от 0 до 999 (дополнив необходимым количеством нулей слева однозначные и двухзначные числа), сумма цифр каждого из которых равна n, то мы получим номер счастливого билета с суммой цифр 2n. Таким образом, количество счастливых номеров, сумма цифр которых равна 2n, будет совпадать с количеством различных пар чисел из указанного диапазона, сумма цифр каждого из которых равна n.
Вот код программы, работающей по описанному выше алгоритму:
Заметим, что мы не стали, на этот раз, перебирать в цикле числа от 0 до 999, а вместо этого построили три вложенных друг в друга цикла, в каждом из которых перебираются цифры от 0 до 9.
Выполнение данной программы приводит к точному такому же выводу на консоль, что и выполнение предыдущей.
Математический подход
Очень часто после того, как некоторая комбинаторная задача решена программным способом, возникает желание попробовать получить чисто математическое решение, для построения которого требуются лист бумаги, ручка и, в крайнем случае, калькулятор, умеющий выполнять 4 арифметических действия. Мне удалось решить задачу о счастливых номерах без использования компьютера, но решение получилось несколько громоздким. Не исключено, что кто-то из читателей сможет предложить более элегантное решение.
Будем для вычисления количества счастливых номеров S использовать выведенную в предыдущем разделе формулу
где ck — количество чисел от 0 до 999, сумма цифр которых равна k.
Пусть Ak — множество всех упорядоченных троек однозначных чисел, сумма которых равна k. Заметим, что заменив в каждом элементе этого множества каждое число разностью числа 9 и данного числа, мы перейдём от множества Ak к множеству A27-k. Таким образом, между множествами Ak и A27-k может быть установлено взаимно однозначное соответствие, откуда следует, что ck = c27-k. С учётом этого равенства формулу для вычисления S можно переписать в виде:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 5, 4, 3, 2, 1.
Рассмотрим упорядоченную тройку однозначных чисел, сумма которых равна k. Пусть сумма второго и третьего чисел равна i. Зададимся вопросом: какие значения может принимать параметр i при фиксированном k? Минимальное значение, которое может принять i (обозначим его imin), очевидно, равно разности k и максимально возможного значения первого числа, равного min(k, 9), т. е.
Если же мы договоримся считать, что индекс i может принимать любые целые значения, но ti = 0 при i 18, то запись ck через сумму может быть упрощена:
Итак, мы выразили ck через ti. Но значения ti нам уже известны, поэтому мы можем теперь заняться теперь выражением сk через k. Для k от 0 до 9 имеем:
Здесь мы использовали хорошо известную формулу суммы первых k натуральных чисел:
Для вычисления последних двух сумм применим следующую формулу суммы n членов арифметической прогрессии a1, a2, …, an :
Итак, нам удалось выразить сk через k для любых k от 0 до 13. Подставим теперь эти найденные выражения в формулу для вычисления количества счастливых номеров:
Найдём каждую из двух последних сумм (обозначим их, в порядке следования, S1 и S2), по-отдельности.
Для нахождения S1 раскроем скобки, стоящие под знаком суммы, разобьём сумму на несколько сумм и вычислим каждую из них. Нам потребуются формула суммы первых n натуральных чисел, приведённая нами ранее, а также следующие общеизвестные формулы квадратов, кубов и четвёртых степеней первых n натуральных чисел:
Для нахождения второй суммы просто вычислим слагаемые и сложим их. Я не вижу особого смысла прибегать, как в предыдущем случае, к использованию нескольких формул, поскольку слагаемых всего 4. Итак, находим S2:
Остаётся вычислить S:
Заключение
Несложно подсчитать вероятность покупки у кондуктора билета со счастливым номером: она равна 0,055252, т. е. немного превышает 5,5%. Вероятность невысока, но если вы часто ездите на трамвае, то, скорее всего, счастливый билет вам когда-нибудь достанется. Давайте, подсчитаем, например, вероятность того, что билет со счастливым номером будет куплен вами хотя бы один раз в течение невисокосного года, если каждый день в течение этого года вы совершаете ровно одну поездку на трамвае:
Девять девяток после запятой. Событие почти достоверное! Впрочем, если вы готовы довольствоваться двумя девятками, то вполне сгодится и квартал (91 день). 91 поездка на трамвае в Санкт-Петербурге на момент написания этой статьи обойдётся в 2730 рублей. Не очень высокая плата за счастье, не правда ли?