Ответы на задачи 24 (С1)
Скачать 1.99 Mb.
|
if a >= n then if b < n then writeln(b+1) else writeln(n+1); Теперь разберем второй вариант, когда a < n. В этом случае есть 1 вариант, когда количество красных шаров равно a, и ленту ленту длиной n можно сдвинуть вправо на min(a+b-n,a) = a + min(b-n,0)= a - n + min(b,n) вправо, поэтому для этого случая имеем if a < n then if b < n then writeln(a+b-n+1) else writeln(a+1); Окончательный вариант доработки сложного условия: if a + b < n then writeln (0) else if a >= n then if b < n then writeln(b+1) else writeln(n+1) else if b < n then writeln(a+b-n+1) else writeln(a+1); Можно сделать и по-другому: if a + b < n then writeln (0) else if (a < n) and (b < n) then writeln (a+b-n+1) else if (a >= n) and (b >= n) then writeln (n+1) else if (a >= n) then writeln (b+1) else writeln (a+1);
var N, product: longint; digit: integer; begin readln(N); product := N mod 10; while N >= 10 do begin digit := N mod 10; product := product * digit; N := N div 10 end; writeln ( product ) end. Составим таблцу изменения переменных:
Из таблицы видим, что
Теперь разберёмся, в чём проблема. Во-первых, из таблицы видим, что последняя цифра 2 дважды вошла в произведение: один раз – до цикла, в результате присваивания начального значения переменной product, а второй раз – на первом шаге цикла. Чтобы снять эту проблему нужно до цикла присвоить переменной product начальное значение 1 (это типичное начальное значение переменной при накоплении произведения, при суммировании обычно используют 0). Во-вторых, самая старшая цифра, 5, не вошла в произведение, потому что цикл остановился раньше времени. Чтобы этого не происходило, нужно написать условие цикла, при котором он останавливается только тогда, когда все цифры рассмотрены (отброшены) и в переменной N осталось значение 0. Таким образом, ответ на второй вопрос вылядит так: Ошибка 1:
Ошибка 2:
Приведем сразу ответ: 1) при вводе числа 532 программа выводит 5. 2) Ошибка 1: начальное значение переменной min_digit строка: min_digit := 0; исправление: min_digit := 9; (любое значение, большее или равное 9) или так: min_digit := N mod 10; (сразу взять последнюю цифру) Ошибка 2: условие изменения переменной min_digit строка: if digit > min_digit then исправление: if digit < min_digit then
Приведем сразу ответ:
3) Ошибка 1: начальное значение переменной count строка: count:= 1; исправление: count:= 0; Ошибка 2: условие в заголовке цикла строка: while N > 1 do begin исправление: while N > 0 do begin
while n>10 do begin n := n mod 10 end; Поскольку цикл начинает работать только при n > 10, при всех значениях n <= 10 (в том числе и для n = 10) будет выведено исходное число. Таким образом, только из-за строгого неравенства в условии цикла программа неверно работает для n = 10 (выдаёт 10 вместо 1). Если условие в заголовке цикла выполнено, то на первом же шаге в переменную n будет записана последняя цифра этого числа (0..9) и цикл сразу закончится, потому что условие n > 10 уже не будет выполняться. Таким образом, для чисел, больших 10, программы выдаёт последнюю цифру, а не первую. Для того, чтобы получить первую цифру, нужно на каждом шаге отсекать последнюю цифру с помощью целочисленного деления на 10 (n div 10).
3) Ошибка 1: в условии цикла должно быть нестрогоге равенство: строка: while n>10 do begin исправление: while n>=10 do begin Ошибка 2: операция в теле цикла строка: n := n mod 10 исправление: n := n div 10
writeln(T); Теперь посмотрим, как строится T: T:=1; while N>0 do begin d := N mod 10; if d<>1 then begin R := R + d*T; T := T+1 end; N := N div 10; end; Алгоритм работы while N>0 do begin ... N := N div 10; end; говорит о том, что мы последовательно отсекаем от N последние цифры, пока это значение не станет равно 0. Значение этой последней цифры перед отсечением сохраняется в переменной d: d := N mod 10; Смотрим, что происходит, если эта цифра не равна 1: R:=0; T:=1; ... if d<>1 then begin R := R + d*T; T := T+1 end; Судя по этой программе, результат накапливается в переменной R, а T служит счётчиком. Поскольку счётчик начинает отсчёт с 1 увеличивается с каждой неединичной цифрой, в конце работы программа он будет на 1 больше, чем количество цифр, отличных от 1. Таким образом, для входного значения 314, в котором 2 цифры, отличные от 1, программа выведет 3. Если наша гипотеза верна, то выводить нужно число R, а не T, это первая ошибка. Далее, для добавления очередного СТАРШЕГО разряда к числу R нужно умножать d не на счётчик, а на 10k, где k – номер разряда, то есть с каждым шагом значение T должно увеличиваться в 10 раз, а не на 1. Это вторая ошибка.
2) Ошибка 1: выводить следует значение переменной R: строка: writeln(T); исправление: writeln(R); Ошибка 2: изменение переменной T в теле цикла строка: T := T+1 исправление: T := T*10
writeln(m); Теперь посмотрим, как строится m: m := 0; while n>=1 do begin d := n mod 10; if d > 1 then begin m := 10*d + m; end; n:= (n – d) div 10; end; Итак, m зависит только от значений d, получаемых на каждом шаге цикла: d := n mod 10; Очевидно, что это последняя цифра в десятичной записи числа. Попробуем применить этот алгоритм к «хорошему» числу 23, оно не содержит ни нулей, ни единиц, мы должны получить 32. Фактически будет так:
Итак, цифры (в переменной d) выделяются правильно, а результат строится неправильно. Фактически программа складывает цифры, умноженные на 10. Это происходит только для тех цифр, которые больше 1, поэтому программа находит сумму цифр, не равных 1, умноженную на 10. Для числа 1984 она выдаст число (9+8+4)*10 = 210. Достаточно сложен второй вопрос: для каких чисел программа выдаст верный результат? Итак, сумма цифр (кроме 1), умноженная на 10, должна быть равна числу, «развёрнутому» наоборот, без единиц. Значит, в числе обязательно должен быть ноль, причём он должен быть самой старшей цифрой, если отбросить все единицы. Очевидно, что тогда старшая цифра исходного числа – единица, причем единиц впереди может быть много. Пусть в числе есть одна неединичная цифра 2 (отличная от 0), тогда подходят числа 102, 1012, 1102 и т.п. Это ответ на второй вопрос. Итак, одну ошибку мы нашли, она в строке m := 10*d + m; Для того, чтобы исправить эту ошибку, нужно поменять m и d в правой части: m := 10*m + d; Проверим, что это на самом деле верно:
Число было действительно «развёрнуто». Однако это не всё, у нас есть ещё одна «подозрительная» цифра, 0. При проверке получаем, что нули тоже отсекаются условным оператором и не включаются в результат, что неверно:
Это значит, что неверное условие if d > 1 then ... его нужно заменить так, чтобы отсекать только единицы: if d <> 1 then ...
2) при вводе числа 102 программа выводит правильный ответ 20. 3) Ошибка 1: неверное изменение переменной: строка: m := 10*d + m; исправление: m := 10*m + d; Ошибка 2: неверное условие строка: if d > 1 then begin... исправление: if d <> 1 then begin... Обратим внимание, что тут есть две провокации-ловушки. Во-первых, обычно при разбиении числа на цифры используют условие while n>0 do ... но приведенный вариант равносилен: while n>=1 do ... Кроме того, запись n:= (n – d) div 10; содержит лишнее действие – вычитание младшей цифры, но это не влияет на результат, поскольку не меняет старшие цифры, а младшая все равно отбрасывается в результате целочисленного деления.
Найдем, где программа формирует результат, то есть, что она выводит: writeln(count); writeln(maximum); Это значит, что count – это счётчик значений, кратных 3, а переменная maximum должна содержать максимальное из этих чисел. При изучении программы смотрим, как изменяются эти переменные: count := 0; maximum := 999; for i:=1 to n do begin read( x ); if x mod 3 = 0 then begin count := count + 1; if x < maximum then maximum := x; end; end; По поводу счётчика особых замечаний нет – начальное значение равно 0, при нахождении каждого числа, кратного 3, его значение увеличивается на 1. А вот условный оператор if x < maximum then maximum := x; говорит о том, что фактически ищется минимум всех подходящих чисел. Кроме того, при начальном значении maximum := 999; Для того, чтобы программа правильно искала не минимум, а максимум, начальное значение должно быть меньше или равно самому меньшему из подходящих чисел (то есть, нулю): maximum := 0; и изменять ее, если очередное значение больше, чем ранее найденный максимум: |