Ответы на задачи 24 (С1)
Скачать 1.99 Mb.
|
sum := N mod 10; while N > 0 do begin digit := N mod 10; if digit mod 3 > 0 then sum := digit; N := N div 10; end; Во-первых, подозрительно, что начальное значение суммы – не ноль, а последняя цифра введённого числа N mod 10 (обычно сумма накапливается, начиная с 1). При этом проверка на кратность 3 не делается, то есть в переменной sum может оказаться начальное значение, кратное 3. Во-вторых, в теле цикла если найдена цифра, не кратная 3, она записывается в sum, стирая старое значение, то есть сумма не накапливается, а постоянно обновляется и в итоге будет равна старшей (последней с конца) цифре, не кратной трём. Теперь очевиден ответ на первый вопрос: 1) при вводе числа 654 будет выведено значение 5. Далее делаем вывод, что при этих условиях верное значение будет выведено тогда, когда в числе есть только одна цифра, не кратная трём (тогда сумма совпадает с этой цифрой).
Остались исправления: 3) в программе нужно исправить две ошибки
Было: sum := N mod 10; Исправление: sum := 0;
Было: sum := digit; Исправление: sum := sum + digit;
Как только мы нашли цифру, кратную 3, нужно записать её в переменную sum (стирая -1!), а если сумма неотрицательна, добавляем к ней эту цифру: if sum < 0 then sum = digit else sum := sum + digit; В остальном подход к решению аналогичен предыдущей задаче. 1) при вводе числа 653 будет выведено значение 6. 2) программа выводит верное значение для трёхзначного числа 113. 3) в программе нужно исправить ТРИ ошибки
Было: sum := N mod 10; Исправление: sum := -1;
Было: sum := digit; Исправление: if sum < 0 then sum = digit else sum := sum + digit;
Было: if sum > 0 then Исправление: if sum > -1 then
Видим, что последовательные значения переменных f и fn повторяют ряд Фибоначчи. При n=4 программы выводит 0, это ответ на первый вопрос. Теперь посмотрим, что выводится на экран (это значения fn-5) и какое значение () мы хотели бы видеть:
Как следует из таблицы, при n=6 программа выводит правильное значение 8. Сравнивая в таблице строки fn и (), находим, что значения fn опережают нужную нам последовательность на 1 шаг из-за того, что фактически наша последовательность начинается с двух единиц, а не с 0 и 1, как требуется. Поэтому в самом начале в переменную fn нужно записать 0, а не 1. Вот правильный ответ: 1) при вводе числа 4 будет выведено значение 0. 2) программа выводит верное значение для числа 6, это значение равно 8. 3) в программе нужно исправить две ошибки
Было: fn := 1; Исправление: fn := 0;
Было: writeln(fn – 5) Исправление: writeln(fn) Возможен другой вариант исправления: 3) в программе нужно исправить две ошибки
Было: f := 1; Исправление: f := 0;
Было: writeln(fn – 5) Исправление: writeln(f)
Цикл останавливается, когда нарушается условие s<=A, то есть значение s становится больше A. В данном случае при A < 6 мы получим результат 2, при A [6; 17] – результат 3, при A [18; 37] – результат 4, при A [38; 67] – результат 5, и т.д. Отсюда следует ответ на первый вопрос: 1) при вводе числа 15 программа выведет ответ 3. В правильной программе переменная k должна принимать только нечётные значения (в исходном варианте k «проходит» по всем натуральным числам). Вычислим соответствующие суммы:
Правильная программа при вводе числа 1 выводит 1, при A [2; 13] – результат 3, при A [14; 43] – результат 5 и т.д. Сравнивая две таблицы, находим, что при A [6; 13] ошибочная программа выводит правильный результат 3, поэтому 2) минимальные значения A, при которых программа выведет правильный результат (равный 3) – это 6 и 7 . Найдём ошибки в программе. Во-первых, переменная k должна изменяться с шагом 2 (через одно значение). То есть, вместо k:=k+1 нужно использовать оператор k:=k+2. Кроме того, после первого увеличения в цикле значение переменной k должно стать равно 1, поэтому начальное значение k должно быть равно –1. 3) в программе нужно исправить две ошибки
Было: k := 1; Исправление: k := -1;
Было: k:=k+1; Исправление: k:=k+2;
1) при вводе числа 15 программа выведет ответ 4. 2) минимальные значения A, большие, чем 10, при которых программа выведет правильный результат (равный 5) – это 20 и 21. 3) в программе нужно исправить три ошибки
Было: k := 0; Исправление: k := 1;
Было: k:=k+1; Исправление: k:=k+2;
Было: writeln(k); Исправление: writeln(k-2);
j := 1; k := 0; while j * j < n do begin if n mod j = 0 then k := k + 2; j := j + 1 end; Каждый раз, когда мы находим делитель, счётчик делителей k увеличивается на 2, так как мы нашли сразу пару. Сравнивая этот фрагмент с программой, приведенной в условии, видим одну ошибку – начальное значение переменной j должно быть равно 1, а не 2, как в программе. Кроме того в конце нужно проверить, не является ли n квадратом целого числа (после окончания цикла оно может быть равно только j!), и если является, нужно добавить ещё один делитель: if j * j = n then k := k + 1; Видим вторую ошибку: в программе k увеличивается на 3, а нужно – на 1. В результате первой ошибки (неверное начальное значение j) получается уменьшение k на 2, а в результате второй – увеличение на 2. Эти две ошибки скомпенсируют друг друга, если случатся одновременно, а это возможно только для чисел, которые являются полными квадратами, большими 1. Минимальные из этих чисел – это 4 и 9. При вводе числа 10 условие j*j=n не выполняется, и значение k будет на 2 меньше, чем нужно, то есть, 4 – 2 = 2 (число 10 имеет 4 делителя). 1) при вводе числа 10 программа выведет неверный ответ 2. 2) минимальные значения n, при которых программа выведет правильный результат (равный 3) – это 4 и 9. 3) в программе нужно исправить две ошибки
Было: j := 2; Исправление: j := 1;
Было: k:=k+3; Исправление: k:=k+1;
1) При вводе числа 157 программа выведет значение 7. Поиск «максимума не из всех» осложняется тем, что мы не можем в качестве начального значения для переменной m взять первую с конца цифру, так как она может быть больше 5 (именно это произошло в примере с числом 157). А в приведённой программе видим: readln(N); m := N mod 10; Поэтому первую ошибку нашли. В теле цикла все вроде бы логично: берём последнюю цифру числа и, если она меньше 5, сравниваем с максимумом из предыдущих. После этого делим число на 10, отбрасывая последнюю цифру. Цикл продолжается до тех пор, пока все цифры не обработаны (и не отброшены) и значение N не стало равно 0. Смотрим на вывод ответа: if m = 0 then writeln('NO') else writeln( m ) При выводе m сравнивается с нулем, который должен сигнализировать о том, что нужных цифр (меньше 5) не нашли. Но 0 – это ведь тоже цифра меньше 5, поэтому она может быть правильным ответом и использовать это значение для обнаружения отсутствия нужных цифр нельзя! Но если наименьшая подходящая цифра – не 0, то вывод работает нормально. Таким образом, программа выдаёт правильный ответ, если в числе есть цифры, которые меньше 5, и последняя цифра (которая становится начальным значением m) тоже меньше 5. Наибольшее такое трёхзначное число – 994. 2) Наибольшее трёхзначное число, для которого программа выдаёт правильный ответ – 994. Итак, мы нашли две проблемы – с начальным значением m и с выводом (проверкой на отсутствие нужных букв). Вариант с начальным значением 0 не работает, например, для числа 909 (тут 0 - правильный ответ). Поэтому можно взять в качестве начального значения –1. Если значение m останется равным –1, то ни одного подходящего числа не нашли – этот факт служит сигналом для вывода «NO». 3) в программе нужно исправить две ошибки
Было: m := N mod 10; Исправление: m := -1;
Было: if m = 0 then Исправление: if m = -1 then
1) При вводе числа 170 программа выведет неверный ответ NO. 2) Наименьшее трёхзначное число, для которого программа выдаёт правильный ответ – 103. 3) в программе нужно исправить две ошибки
Было: m := 0; Исправление: m := -1;
Было: if m = 0 then Исправление: if m = -1 then 1 Аналогичная ситуация возникает при решении уравнения методом деления отрезка пополам (кто помнит :-). 2 Согласно решению, приведенному авторами задачи, при составлении таблицы рассматриваются только внутренние точки интервалов, то есть все, кроме их концов. http://kpolyakov.spb.ru |