Главная страница

Ответы на задачи 24 (С1)


Скачать 1.99 Mb.
НазваниеОтветы на задачи 24 (С1)
Дата21.04.2018
Размер1.99 Mb.
Формат файлаdoc
Имя файлаansw24-C1.doc
ТипПрограмма
#41783
страница14 из 18
1   ...   10   11   12   13   14   15   16   17   18

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);

  1. Сначала выполним первое задание, подставив значение N = 532 в программу:

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.

Составим таблцу изменения переменных:

оператор

N

digit

product




?

?

?

readln(N);

532







product := N mod 10;







2

N >= 10?

да

digit := N mod 10;




2




product := product * digit;







4

N := N div 10

53







N >= 10?

да

digit := N mod 10;




3




product := product * digit;







12

N := N div 10

5







N >= 10?

нет

writeln ( product )







12

Из таблицы видим, что

  1. При вводе числа 532 программа выдает 12, это ответ на первый вопрос.

  2. Программа работает неверно, то есть, неправильно вычисляет произведеие цифр.

Теперь разберёмся, в чём проблема. Во-первых, из таблицы видим, что последняя цифра 2 дважды вошла в произведение: один раз – до цикла, в результате присваивания начального значения переменной product, а второй раз – на первом шаге цикла. Чтобы снять эту проблему нужно до цикла присвоить переменной product начальное значение 1 (это типичное начальное значение переменной при накоплении произведения, при суммировании обычно используют 0).

Во-вторых, самая старшая цифра, 5, не вошла в произведение, потому что цикл остановился раньше времени. Чтобы этого не происходило, нужно написать условие цикла, при котором он останавливается только тогда, когда все цифры рассмотрены (отброшены) и в переменной N осталось значение 0.

Таким образом, ответ на второй вопрос вылядит так:

Ошибка 1:

  1. строка перед циклом product := N mod 10;

  2. исправление: product := 1;

Ошибка 2:

  1. заголовок цикла while N >= 10 do begin

  2. исправление: while N > 0 do begin

  1. Эта задача полностью аналогична задаче 45. На самом деле, приведённая программа выводит наибольшую цифру введённого числа.

Приведем сразу ответ:

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

  1. Эта задача аналогична задаче 45.

Приведем сразу ответ:

  1. при вводе числа 123 программа выводит 3 (правильный ответ).

  2. программа работает неверно для любого числа, у которого старшая цифра больше 1, например, для числа 232

3) Ошибка 1: начальное значение переменной count

строка: count:= 1;

исправление: count:= 0;

Ошибка 2: условие в заголовке цикла

строка: while N > 1 do begin

исправление: while N > 0 do begin

  1. Рассмотрим цикл, приведенный в программе:

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).

  1. при вводе числа 1984 программа выводит 4 (неправильный ответ).

  2. программа работает верно для любого числа, у которого старшая цифра равна младшей, в том числе для любого однозначного числа

3) Ошибка 1: в условии цикла должно быть нестрогоге равенство:

строка: while n>10 do begin

исправление: while n>=10 do begin

Ошибка 2: операция в теле цикла

строка: n := n mod 10

исправление: n := n div 10

  1. Во–первых, найдем, где программа формирует результат, что есть, что она выводит:

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. Это вторая ошибка.

  1. при вводе числа 314 программа выводит 3 (неправильный ответ).

2) Ошибка 1: выводить следует значение переменной R:

строка: writeln(T);

исправление: writeln(R);

Ошибка 2: изменение переменной T в теле цикла

строка: T := T+1

исправление: T := T*10

  1. Во–первых, найдем, где программа формирует результат, то есть, что она выводит:

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. Фактически будет так:

n

d

m

23




0




3

30

2

2

50

Итак, цифры (в переменной 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;

Проверим, что это на самом деле верно:

n

d

m

23




0




3

3

2

2

32

Число было действительно «развёрнуто». Однако это не всё, у нас есть ещё одна «подозрительная» цифра, 0. При проверке получаем, что нули тоже отсекаются условным оператором и не включаются в результат, что неверно:

n

d

m

203




0




3

3

20

0




2

2

32

Это значит, что неверное условие

if d > 1 then ...

его нужно заменить так, чтобы отсекать только единицы:

if d <> 1 then ...

  1. при вводе числа 1984 программа выводит 210 (неправильный ответ).

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;

содержит лишнее действие – вычитание младшей цифры, но это не влияет на результат, поскольку не меняет старшие цифры, а младшая все равно отбрасывается в результате целочисленного деления.

  1. Сразу обратим внимание, что два блока var в программе на Паскале допустимы и не являются ошибкой.

Найдем, где программа формирует результат, то есть, что она выводит:

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;

и изменять ее, если очередное значение больше, чем ранее найденный максимум:
1   ...   10   11   12   13   14   15   16   17   18


написать администратору сайта