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

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


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

if x > maximum then

maximum := x;

  1. При входных данных 2 9 4 3 программа выведет сначала число 2 (есть 2 значения, кратные 3), а потом – число 3 (минимальное из чисел, кратных 3).

  2. При входных данных 1 2 3 4 программа выведет правильный ответ (минимальное число, кратное 3, равно максимальному).

  3. Исправление ошибок:

    1. Строка с ошибкой: maximum:=999;
      исправление
      maximum:=0; (или любое отрицательное число)

    2. Строка с ошибкой: if x < maximum then
      исправление if x > maximum then


  1. Эта задача очень похожа на задачу, которая была полностью разобрана в файле с теорией. Фактически программа вычисляет количество цифр числа, увеличенное на единицу. Приведём правильный ответ.

  1. при вводе числа 256 программа выведет число 4.

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

  3. в программе нужно исправить две ошибки:

а) неверное начальное значение переменной sum:

Было: sum := 1;

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

б) неверное увеличение суммы

Было: sum := sum + 1;

Исправление: sum := sum + d;

  1. Эта задача очень похожа на задачу, которая была полностью разобрана в файле с теорией. Фактически программа выводит старшую цифру числа. Приведём правильный ответ.

  1. при вводе числа 256 программа выведет число 2.

  2. программа выводит правильный ответ, если сумма цифр равна старшей цифре числа, например, для числа 300.

  3. в программе нужно исправить две ошибки:

а) неверное начальное значение переменной sum:

Было: sum:= 1;

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

б) неверное увеличение суммы

Было: sum := d;

Исправление: sum := sum + d;

  1. Программа выводит значение счётчика cnt. Начальное значение счётчика – ноль, с каждым шагом цикла его значение увеличивается на x mod 2, то есть на остаток от деления числа на 2 – на последнюю цифру записи числа в двоичной системе счисления.

Выполним трассировку для числа 15:

Оператор

Условие

x

cnt

readln(x);




15




cnt:=0;







0

x > 0 ?

да







cnt:=cnt + x mod 2;







1

x := x div 10




1




x > 0 ?

да







cnt:=cnt + x mod 2;







2

x := x div 10




0




x > 0 ?

нет







  1. при вводе числа 15 программа выведет число 2.

Самый сложный вопрос в этой задаче – второй (когда программа сработает верно). Как следует из трассировки, на каждом шаге отсекается одна десятичная цифра числа, поэтому это может быть только однозначное число. Для однозначного числа выполнится один шаг цикла, при этом счётчик будет увеличен на 1, если число нечётное, или останется равным 0, если число чётное. Чисел, которые содержат 0 цифр в двоичной системе нет, и есть только одно число – 1, – которое содержит одну цифру. Поэтому единственный правильный ответ:

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

Ошибок в программе две. Во-первых, когда мы считаем цифры двоичной записи, нужно отсекать цифры не в десятичной записи числа, а в двоичной. Поэтому делить нужно не на 10, а на 2. Во-вторых, при каждом отсечении нужно увеличивать счётчик ровно на 1.

  1. в программе нужно исправить две ошибки:

а) неверное учеличение счётчика cnt:

Было: cnt:=cnt + x mod 2;

Исправление: cnt:=cnt + 1;

б) неверное изменение переменной x:

Было: x:=x div 10;

Исправление: x:=x div 2;

  1. Программа выводит значение счётчика cnt. Начальное значение счётчика – ноль, с каждым шагом цикла его значение увеличивается на 1.

Выполним трассировку для числа 6:

Оператор

Условие

x

cnt

readln(x);




6




cnt:=0;







0

x > 0 ?

да







cnt:=cnt + 1;







1

x := x mod 2;




0




x > 0 ?

нет







  1. при вводе числа 6 программа выведет число 1.

Самый сложный вопрос в этой задаче – второй (когда программа сработает верно). Как следует из трассировки, если введено чётное число, на первом же шаге значение x становится равно 0 (остатку от его деления на 2) и цикл завершается. При этом выводится значение 1. Если же вводится нечётное число, то значение x остаётся равным 1 и далее не изменяется, так что программа зацикливается.

Таким образом, программа выводит правильный ответ для чётных чисел, которые содержат одну единицу в двоичной записи, то есть, для натуральных степеней числа 2: чисел 2, 4, 8, 16 и т.д.

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

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

  1. в программе нужно исправить две ошибки:

а) неверное увеличение счётчика cnt:

Было: cnt:=cnt + 1;

Исправление: if x mod 2 = 1 then cnt:=cnt + 1;

или так:

Исправление: cnt:=cnt + x mod 2;

б) неверное изменение переменной x:

Было: x:=x mod 2;

Исправление: x:=x div 2;

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

При вводе значения 0,4 условие s <= а неверно при входе в цикл, поэтому цикл не выполнится ни разу, и будет выведено значение k = 1:

  1. при вводе числа 0,4 программа выведет число 1

Теперь выясним, когда программа выводит ответ 2. Это означает, что цикл выполнится ровно 1 раз, и переменная k увеличится с начального значения 1 до 2. Заметим, что для этого нужно, чтобы

  1. выполнялось условие 1  A, при этом условие цикла в самом начале верно и цикл будет выполнен, по крайней мере, один раз;

  2. выполнялось условие (1/2) > A, иначе цикл не закончится после первого шага.

Очевидно, что условия a) и б) не могут выполняться одновременно ни для какого A, поэтому

  1. ни для одного A программа не выведет число 2

Займемся исправлением программы. Во-первых, заметим что в переменной s НЕ накапливается сумма, новое слагаемое нужно прибавлять к предыдущему значению s:

s := s + 1.0 / k;

Вторая ошибка более тонкая: в условии окончания цикла стоит нестрогое неравенство, поэтому в условии продолжения цикла должно стоять обратное условие – строгое равенство: s < a.

  1. в программе нужно исправить две ошибки:

а) неверное условие цикла:

Было: while s <= a do begin

Исправление: while s < a do begin

б) неверное изменение переменной s:

Было: s:= 1.0/k;

Исправление: s:= s + 1.0/k;

  1. Программа выводит значение переменной k – искомого натурального числа. Начальное значение k равно 0, с каждым шагом цикла его значение увеличивается на 1.

При вводе значения 1,4 условие s >= а неверно при входе в цикл, поэтому цикл не выполнится ни разу, и будет выведено значение k = 0:

  1. при вводе числа 1,4 программа выведет число 0

Теперь выясним, когда программа выводит ответ 1. Это означает, что цикл выполнится ровно 1 раз, и переменная k увеличится с начального значения 0 до 1. Заметим, что для этого нужно, чтобы

  1. выполнялось условие 1  A, при этом условие цикла в самом начале верно и цикл будет выполнен, по крайней мере, один раз;

  2. выполнялось условие (1+1) < A, иначе цикл не закончится после первого шага.

Очевидно, что условия a) и б) не могут выполняться одновременно ни для какого A, поэтому

  1. ни для одного натурального A программа не выведет число 1

Займемся исправлением программы. Во-первых, заметим что начальное значение переменной s (где накапливается сумма) не равно нулю для k = 0, это первая ошибка, её нужно исправить:

s := 0;

Вторая ошибка – в условии. В заданном условии окончания цикла стоит нестрогое неравенство, поэтому в условии продолжения цикла должно стоять обратное условие – строгое равенство: s < a.

  1. в программе нужно исправить две ошибки:

а) неверное начальное значение переменной s:

Было: s:= 1;

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

б) неверное условие цикла:

Было: while s >= a do begin

Исправление: while s < a do begin

Заметим, что ошибку а) можно исправить и по-другому:

а) неверное начальное значение переменной k:

Было: k:= 0;

Исправление: k:= 1;

  1. Программа выводит значение переменных x и p, первое должно обозначать количество неотрицательных чисел, а второе – их произведение. Проверим, что получается при вводе последовательности -5 2 1 3.

В цикле обнаруживаем оператор ввода

read(x);

который говорит о том, что в переменной x хранится последнее введённое число (а не счётчик неотрицательных чисел!).

Это число обрабатывается условным оператором

if x >= 0 then begin

p := p*x;

count := count+1

end

Из этих строк следует, что переменная p накапливает произведение неотрицательных чисел, а переменная count – это счётчик неотрицательных чисел, который и нужно вывести на экран в конце программы.

Сначала обе переменные обнуляются, поэтому значение p так и останется равным нулю (умножив ноль на любое число, мы получим ноль). Это явная ошибка.

В то же время счётчик работает верно, и на самом деле переменная count будет содержать количество неотрицательных чисел (это можно проверить ручной прокруткой).

После окончания цикла выводится значение x – последнее введённое число, и значение p, которое всегда будет равно нулю.

Таким образом,

  1. при вводе чисел -5 2 1 3 программа выведет числа 3 и 0.

Теперь отвечаем на второй вопрос – когда же программа сработает верно, несмотря на ошибки. Второе число всегда будет равно 0, поэтому в последовательности должен быть 0. В то же время последнее введённое число, которое останется в переменной x и будет выведено, должно быть равно количеству неотрицательных чисел. Эти условия выполняются, например для последовательности -5 0 1 3.

  1. при вводе последовательности -5 0 1 3 программа выдает правильный ответ.

Ошибки мы уже фактически нашли ранее: во-первых, для накопления произведения переменную p не нужно обнулять, а нужно записывать в неё начальное значение 1. Во-вторых, выводить нужно не x, а count.

  1. в программе нужно исправить две ошибки:

а) неверное начальное значение переменной p:

Было: p:= 0;

Исправление: p:= 1;

б) неверный оператор вывода:

Было: writeln(x);

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

  1. Программа выводит значение переменных s и mx, первое должно обозначать сумму отрицательных чисел, а второе – максимальное число в последовательности. Проверим, что получается при вводе последовательности -5 2 -4 3.

В цикле обнаруживаем оператор ввода

read(x);

который говорит о том, что в переменной x хранится последнее введённое число (а не счётчик неотрицательных чисел!).

Это число обрабатывается условными операторами

if x < 0 then

s := x;

if x > mx then

mx := x;

Из этих строк следует, что в переменную s записывается последнее отрицательное число, а переменная mx – это максимальное из всех элементов последовательности. Сначала обе переменные обнуляются.

Таким образом,

  1. при вводе чисел -5 2 -4 3 программа выведет числа -4 и 3.

Программа неверно подсчитала сумму отрицательных чисел, вместо неё выведено последнее отрицательное число. Поэтому первое значение будет правильным, если это отрицательное число всего одно.

Обратим внимание, что начальное значение переменной mx равно 0, поэтому если все числа меньше нуля, максимум будет вычислен неверно. Для правильной программы это начальное значение должно быть не больше, чем минимальное допустимое число, то есть -1000.

Таким образом, программа сработает верно, если в последовательности только одно отрицательное число. Это условия выполняются, например для последовательности -5 0 1 3.

  1. при вводе последовательности -5 0 1 3 программа выдает правильный ответ.

Одну ошибку мы уже нашли ранее: начальное значение для переменной mx должно быть не более -1000. Вторая ошибка – сумма отрицательных чисел не накапливается.

  1. в программе нужно исправить две ошибки:

а) неверное начальное значение переменной mx:

Было: mx:= 0;

Исправление: mx:= -1000;

б) неверный оператор накопления суммы:

Было: s:=x;

Исправление: s:=s+x;

  1. Проверим, что получается при вводе числа N = 134.

Сначала в переменную maxDigit записывается начальное значение N mod 10, это последняя цифра в десятичной записи числа, она равна 4. Заметим, что проверки на делимость этой цифры на 3 не было!

Затем в цикле перебираются все цифры числа в обратном порядке (4, 3 и 1), если очередная цифра делится на 3 и больше, чем существующее значение maxDigit, значение maxDigit обновляется – мы нашли новый максимум. в данном случае цифр больше, чем 4, в числе нет, поэтому после окончания цикла maxDigit=4, это число и выводится на экран.

  1. При вводе числа 134 программы выводит число 4.

Программа будет выводить правильный ответ, если последняя цифра делится на 3 (например, для числа 136). Есть и другой вариант – когда последняя цифра меньше, чем наибольшая цифра, которая делится на 3 (например, для числа 631).

  1. Программа выведет правильный ответ при вводе числа 136.

Для того, чтобы исправить программу, нужно изменить начальное значение maxDigit. Проще всего взять значение, заведомо меньшее, чем любая цифра, например, -1.

Поскольку ноль делится на любое число, проверка условия maxDigit=0 не поможет определить, есть ли в числе цифра, кратная трём. Это условие нужно заменить на maxDigit=-1.

  1. В программе нужно исправить две ошибки:

а) Было: maxDigit := N mod 10;

Исправление: maxDigit := -1;

б) Было: if maxDigit=0 then

Исправление: if maxDigit=-1 then

  1. Задача аналогична задача 57, поэтому приведем только решение с небольшими комментариями.

  1. при вводе числа 1.8 программа выведет число 1 (проверяется ручной прокруткой).

В программе сделано несколько ошибок, и в некоторых случаях они могут скомпенсировать друг друга. Во-первых, цикл заканчивается, когда sa, то есть мы всегда находим k, которое на единицу больше правильного значения. С другой стороны, перед циклом стоит два присваивания:
1   ...   10   11   12   13   14   15   16   17   18


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