Ссылка на условие задания: e-olymp.
Условие
Часы с боем пробивают каждый час такое количество ударов, сколько их есть на циферблате с цифрами от 1 до 12, и по одному разу тогда, когда минутная стрелка указывает на цифру 6. Зная начальное и конечное время в рамках одних календарных суток (выраженное в часах и минутах), подсчитать общее количество ударов на этом промежутке времени.
Входные данные.
Начальное и конечное время одних календарных суток в часах ($H$) и минутах ($M$) через пробел ([latex]0 \leq H \leq 23, 0 \leq M \leq 59[/latex]).
Выходные данные.
Ответ на задачу.
Тесты
Входные данные | Выходные данные |
---|---|
Начальное и конечное время | Количество ударов |
13 30 15 10 | 7 |
0 00 23 59 | 180 |
12 30 12 30 | 1 |
22 22 22 25 | 0 |
Код.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class Test { static function main() { var output = Sys.stdout(); var h1:Int = Std.parseInt(Sys.stdin().readLine()); var m1:Int = Std.parseInt(Sys.stdin().readLine()); var h2:Int = Std.parseInt(Sys.stdin().readLine()); var m2:Int = Std.parseInt(Sys.stdin().readLine()); var res:Int = 0; while((h2*60+m2)-(h1*60+m1) >= 0) { if(m1 == 59) { h1++; m1 = 0; } if(m1 == 30) { res++; } if (m1 == 0) { res+=h1%12; } m1++; } output.writeString(res); } } |
Решение.
Заведем переменную, которая будет отвечать за количество пробитых ударов
res. Если на часах 59 минут, то увеличиваем количество часов
h1, и обнуляем значение минутной стрелки
m1, для следующего круга. Если значение минутной стрелки равно 30 то увеличиваем переменную
res на один. Если же минутная стрелка на 12, то есть 0 минут, то к
res добавляем остаток от деления текущего количества часов на 12. Увеличиваем значение переменной
m1 на 1. Повторяем, пока начальное время не будет совпадать с конечным.
Ссылка на решение задачи на сайте Try Haxe!
Альтернативное решение.
Также существует способ решения этой задачи без использования циклов. Для этого я использовала функцию FactTree, которая реализует арифметическую прогрессию. Эта функция считает сколько ударов совершили часы от 0 часов, до указанного в качестве параметра времени. Объясним принцип работы функции ProdTree.Пусть нам нужно найти сумму последовательных чисел от L до R, обозначим его как P(L, R). Разделим интервал от L до R пополам и посчитаем P(L, R) как P(L, M) + P(M + 1, R), где M находится посередине между L и R, M = (L + R) / 2. Заметим, что слагаемые будут примерно одинаковой длины. Аналогично разобьем P(L, M) и P(M + 1, R). Будем производить эту операцию, пока в каждом интервале останется не более двух слагаемых. Очевидно, что P(L, R) = L, если L и R равны, и P(L, R) = L + R, если L и R отличаются на единицу.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
class Test { static function ProdTree(l:Int, r:Int):Int { if (l > r) return 1; if (l == r) return l; if (r - l == 1) return l + r; var m = Math.floor((l + r) / 2); return ProdTree(l, m) + ProdTree(m + 1, r); } static function FactTree(n:Int):Int { if (n < 0) return 0; if (n == 0) return 1; if (n == 1 || n == 2) return n; return ProdTree(2, n)+1; } static function res(h1:Int, m1:Int, h2:Int, m2:Int):Int { var q = h2 - h1; if (q == 0) { if((m1 < 30 && m2 > 30 && m1!=0)|| m1 == 30|| m2 == 30) return 1; if ((m1 < 30 && m2 < 30 && m1 != 0 && m2 != 0)||(m1 > 30 && m2 > 30)) return 0; if(m1 == 0 || m2 == 0) return h2; } if (q <= 12) { if (h1 > 12) h1 = h1 - 12; if (h2 > 12) h2 = h2 - 12; var r = FactTree(h2) - FactTree(h1); if(m1 < 30 && m2 < 30 && m1 !=0 && m2 != 0) return r + q - FactTree(h1); if (m1 == 0 && m2 < 30) return r + q; if(m1 > 30 && m2 > 30) return r + q; if(m1 > 30) return r + q - 1; if(m2 > 30) return r + q + 1; if (m1 == 30) return r + q; if (m2 == 30) return r + q + 1; } var h22 = h2 - 12; q = h22-h1; var r; if (h1 > 12) h1 = h1 - 12; if (h1 == 0) r = FactTree(h22) + 12; else r = FactTree(h22) - FactTree(h1); if(m1 < 30 && m2 < 30 && m1 !=0 && m2 != 0) return (r + q - FactTree(h1))*2; if (m1 == 0 && m2 < 30) return (r + q)*2; if (m1 == 0 && m2 > 30) return (r + q + 1)*2; if(m1 > 30 && m2 > 30) return (r + q)*2; if(m1 > 30) return (r + q - 1)*2; if(m2 > 30) return (r + q + 1)*2; if (m1 == 30) return (r + q)*2; if (m2 == 30) return (r + q + 1)*2; return 0; } static function main() { var output = Sys.stdout(); var h1:Int = Std.parseInt(Sys.stdin().readLine()); var m1:Int = Std.parseInt(Sys.stdin().readLine()); var h2:Int = Std.parseInt(Sys.stdin().readLine()); var m2:Int = Std.parseInt(Sys.stdin().readLine()); output.writeString(res(h1,m1,h2,m2)); } } |
Ссылка на решение задачи на сайте Try Haxe!
- e-olymp 2166: Анаграммы - 02.06.2017
- e-olymp 7365. Молоко и пирожок - 20.05.2017
- A710 - 17.05.2017
Задача на циклы и решена с использованием циклов. Конечно зачтено.
Но есть вопрос — а существует решение без циклов?
Спасибо за интересный вопрос. Я нашла альтернативное решение.
Засчитываю как упражнение, но второе решение может быть много короче.
Но я бы сделал проще:
Убрал комментарии, чтобы помучились разбирать трюки 🙂
Основная идея, чтобы посчитать количество ударов до назначенного времени. потом вычитанием находим количество ударов на отрезке. Правда пришлось исключить удары в начальный момент времени отняв 1 минуту.