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

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


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

t := 1;

Это первая ошибка в программе. Она всегда увеличивает значение k на 1.

Перебор значений k начинается с 1 и продолжается пока выполняется условие K3 <= N. Внутри цикла проверяется нижняя граница:

if k*k*k > m then t := t + 1;

но это неравенство строгое, а нам задано нестрогое неравенство. Это вторая ошибка. Уменьшает значение k на 1 (в сравнении с правильным) для тех случаев, когда M – это куб какого-то целого числа. Что произойдет при вводе чисел 10 и 100? Между ними находятся кубы двух чисел: 27 = 33 и 64 = 43. Кроме того, переменная t будет увеличена на 1 из-за неправильной инициализации. Число 10 – это не точный куб, поэтому уменьшения значения t в результате второй ошибки не будет. Программа выдаст число 3.

Две ошибки скомпенсируются и программа выдаст правильный ответ, если M – точный куб какого-то целого числа. Например, 1, 8, 27 и т.д.

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

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

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

    1. Неверное начальное значение t:

Было: t:=1;

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

    1. Неверное условие:

Было: if k*k*k > m then

Исправление: if k*k*k >= m then

  1. Эта задача полностью аналогична задаче 66, поэтому приведём только ответы на вопросы:

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

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

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

    1. Неверное начальное значение t:

Было: t:=1;

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

    1. Неверное условие:

Было: while k*k < n do begin

Исправление: while k*k <= n do begin

  1. Для того чтобы выполнить первое задание, используем трассировку (ручную прокрутку):




условие верно?

n

k







25




k := 0;







0

k mod 5 = 0?

да







k := k + 1;







1

n := n div 5;




5




k mod 5 = 0?

нет







k = 1?

да







Поскольку после завершения цикла k=1, то

  1. для входного числа n=25 будет выведено значение 1.

Для ответа на второй вопрос обратим внимание, что конечное значение переменной k никак не зависит от n, и программа ВСЕГДА будет выводить результат 1. Поэтому

  1. программа работает правильно только при n=51=5.

Чтобы исправить программу, нужно понять алгоритм её работы, как задумывал автор (но не реализовал). Очевидно, что k – это счётчик, с помощью которого мы считаем степень числа 5. Оператор

n := n div 5;

говорит о том, что предполагалось делить исходное число на 5 до тех пор, пока оно делится, и считать, сколько раз нам удалось разделить его на 5 без остатка. Поэтому условие работы цикла должно быть записано как «пока n делится на 5», то есть

while n mod 5 = 0 do begin

...

end;

Одна ошибка найдена.

Если введённое число – это степень числа 5, то оно будет делиться на 5 до тех пор, пока в переменной n не останется 1. Таким образом, условие «число представляет собой натуральную степень числа 5» после цикла запишется в виде

if n = 1 then

...

Это вторая ошибка. Итак, ответ на третий вопрос таков:

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

    1. Неверное условие цикла:

Было: while k mod 5 = 0 do begin

Исправление: while n mod 5 = 0 do begin

    1. Неверное условие в условном операторе:

Было: if k = 1 then

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

  1. Эта задача аналогична предыдущей, поэтому приведём только окончательные ответы:

  1. для входного числа n=49 будет выведено значение 8.

2) программа работает правильно при n=71=7 (выводит 1).

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

  1. Неверное изменение счётчика k:

Было: k := k + n div 7;

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

  1. Неверное условие при выводе ответа:

Было: if n <= 7 then

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

  1. Эта задача аналогична задаче 68, поэтому приведём только окончательные ответы:

1) для входного числа n=16 будет выведено «не существует».

2) программа работает правильно при n=41=4 (выводит 1).

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

  1. Неверное изменение счётчика k:

Было: k := k + n div 4;

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

  1. Неверное условие при выводе ответа:

Было: if k = 1 then

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

  1. Эта задача аналогична задаче 69, поэтому приведём только окончательные ответы:

  1. для входного числа n=9 будет выведено значение 1.

2) программа работает правильно при n=31=3 (выводит 1) или n=2 (выводит «Не существует»).

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

  1. Неверное условие цикла::

Было: while k mod 3 = 0 do begin

Исправление: while n mod 3 = 0 do begin

  1. Неверное условие при выводе ответа:

Было: if n > 0 then

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

  1. С помощью ручной трассировки убеждаемся, что при вводе числа 11 программа выдаёт ответ 3:




s

k

A

read(A)







11

s := 0

0







k := -1




-1




s < A  да










k := k + 1




0




s := s + k*k

0







s < A  да










k := k + 1




1




s := s + k*k

1







s < A  да










k := k + 1




2




s := s + k*k

5







s < A  да










k := k + 1




3




s := s + k*k

14







s < A  нет










  1. для входного числа n=11 будет выведено значение 3.

В ходе трассировки мы увидели проблему: переменная k изменяется с шагом 1 (а не 2!) и проходит как чётные, так и нечётные числа. Кроме того, цикл заканчивается тогда, когда s равно A (потому что нарушается условие s < A), а должен заканчиваться только при s > A. Отсюда сразу следует ответ на третий вопрос:

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

  1. Неверное изменение переменной k:

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

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

  1. Неверное условие цикла:

Было: while s < A do begin

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

Остается ответить на второй вопрос: при каком наименьшем A программа выдает правильный ответ. Построим таблицы изменения переменных s и k для неправильной программы:

k

1

2

3

4

s

1

5

14

30

Поскольку цикл завершается при s  a, при A = 1 программа выдаёт ответ 1, при 2  A  5 – ответ 2, при 6  A  15 – ответ 3 и т.д.

Для правильного решения:

k

1

3

5

s

1

10

35

Мы должны получить при 1  A  9 – ответ 3, при 10  A  34 – ответ 5 и т.д. Отсюда следует, что программа выдаёт верный ответ 3 при 6  A  9, минимальное из этих значений – 6.

2) минимальное значение А, при котором программа работает правильно, равно 6.

  1. С помощью ручной трассировки убеждаемся, что при вводе числа 11 программа выдаёт ответ 4:




s

k

A

read(A)







11

s := 0

0







k := 1




1




s <= A  да










s := s + k*k

1







k := k + 1




2




s <= A  да










s := s + k*k

5







k := k + 1




3




s <= A  да










s := s + k*k

14







k := k + 1




4




s <= A  нет










1) для входного числа n=11 будет выведено значение 4.

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

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

  1. Неверное изменение переменной k:

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

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

  1. Неверный вывод результата:

Было: writeln(k);

Исправление: writeln(k-2); {вернуться на шаг назад}

Остается ответить на второй вопрос: при каком наименьшем A программа выдает правильный ответ. Построим таблицы изменения переменных s и k для неправильной программы:

k

1

2

3

4

s

1

5

14

30

Поскольку программа выводит следующее значение k, при 1  A  4 она выдаёт ответ 3, при 5  A  13 – ответ 4 и т.д.

Для правильного решения:

k

1

3

5

s

1

10

35

Мы должны получить при 1  A  9 – ответ 3, при 10  A  34 – ответ 5 и т.д. Отсюда следует, что программа выдаёт верный ответ 3 при 1  A  4, минимальное из этих значений – 1.

2) минимальное значение А, при котором программа работает правильно, равно 1.

  1. С помощью ручной трассировки убеждаемся, что при вводе числа 12 программа выдаёт ответ 5.




p

s

k

A

read(A)










12

s := 0




0







p := 0

0










k := 1







1




s < A  да













p := p + k

1










s := s + p




1







k := k + 1







2




s < A  да













p := p + k

3










s := s + p




4







k := k + 1







3




s < A  да













p := p + k

6










s := s + p




10







k := k + 1







4




s < A  да













p := p + k

10










s := s + p




20







k := k + 1







5




s < A  нет













1) при вводе числа 12 будет выведено значение 5.

Замечаем, про цикл заканчивается, когда s  k, а нам нужно строгое неравенство. Поэтому необходимо поменять условие цикла на s  a. Кроме того, программа выводит следующее значение k, потому что k увеличивается после того, как увеличились переменные p и s. Поэтому нужно выводить значение k-1, меньшее на единицу.

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

  1. Неверное условие цикла:

Было: while s < A do begin

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

  1. Неверный вывод результата:

Было: writeln(k);

Исправление: writeln(k-1); {вернуться на шаг назад}

Остается ответить на вопрос 2 – найти значение A, при котором программа выдаёт правильный ответ. Во-первых, подбором сразу находим, что при A = 1 программа выдаёт правильный ответ 2. Кроме того, есть и другие варианты. Из-за неверного условия цикл останавливается на шаг раньше, если s = A, при этом выводится следующее, то есть правильное значение k. Такая ситуация происходит при A = 1, A = 1 + (1+2) = 4, A = 1 + (1+2) + (1+2+3) = 10 и т.д.

2) при А = 1 программа выводит правильный ответ 2.

  1. С помощью ручной трассировки убеждаемся, что при вводе числа 12 программа выдаёт ответ 4.




k

p

s

A

read(A)










12

s := 0







0




p := 0




0







k := 1

1










s <= A  да













k := k + 1

2










p := p + k




2







s := s + p







2




s <= A  да













k := k + 1

3










p := p + k




5







s := s + p







7




s <= A  да













k := k + 1

4










p := p + k




9







s := s + p







16




s <= A  нет













1) при вводе числа 12 будет выведено значение 4.

Замечаем, про цикл заканчивается, когда значение k = 1 не учитывается при суммировании, так как в начале тела цикла k сразу увеличивается на 1. Поэтому необходимо поменять начальное значение k на 0. Кроме того, программа выводит следующее значение k, потому что цикл заканчивается тогда, когда нарушается условие s  A, а нам нужно найти последнее k, при котором это условие истинно. Поэтому нужно выводить значение k-1, меньшее на единицу.

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

  1. Неверное начальное значение k:

Было: k := 1;

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

  1. Неверный вывод результата:

Было: writeln(k);

Исправление: writeln(k-1); {вернуться на шаг назад}

Остается ответить на вопрос 2 – найти значения A, при котором программа выдаёт ответ 4. Построим таблицу, связывающую соответствующие значения переменных k, p и s:

k

1

2

3

4

p

0

2

5

9

s

0

2

7

16

Цикл завершается, когда s > A, поэтому программа выдаёт ответ 4 для всех 7  A  15.

2) для всех 7  A  15 программа выводит ответ 4.

  1. С помощью ручной трассировки определяем результат работы программы при вводе чисел 5 и 15:




k

s

A

B

read(A, B)







5

15

s := 1




1







k := A

5










s <= B  да













k := k + 1

6










s := s + k




7







s <= B  да













k := k + 1

7










s := s + k




14







s <= B  да













k := k + 1

8










s := s + k




22







s <= B  нет













1) при вводе чисел 5 и 15 будет выведено значение 8.

Замечаем, что вместо первого числа (5) в сумму добавляется 1. Поэтому первое необходимое исправление – начальное значение переменной s должно быть равно A, а не 1. Кроме того, цикл останавливается, когда сумма становится строго больше B, а нам нужно, чтобы остановка произошла при s  B, поэтому нужно изменить условие цикла:

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

  1. Неверное начальное значение s:

Было: s := 1;

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

  1. Неверное условие цикла:

Было: while s <= B do begin;

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

Теперь остается найти пару значений A и B, при которых программа выдаёт правильный ответ. Для этого нужно определить, что же действительно считает эта программа. Как мы видели, она находит сумму

s = 1 + (A+1) + (A+2) + …

и заканчивает работу, когда эта сумма станет строго больше, чем B. За счёт того, что первое слагаемое равно 1 вместо A, сумма получается меньше, чем нужно, на A-1. С другой стороны, цикл в некоторых случаях (когда получается сумма, строго равная B) продолжается лишний шаг из-за неверного условия цикла. Эти две ошибки могут скомпенсировать друг друга. Построим таблицу значений s для различных k при некотором A:

k

A

A+1

A+2

A+3

s

1

A+2

2A+4

3A+7

Цикл заканчивается, когда s > B, то есть для всех A  B  A+1 получаем результат A+1, для A+2  B  2A+3 получаем значение A+2 и т.д. Сравним эти результаты с правильными:

k

A

A+1

A+2

A+3

s

A

2A+1

3A+3

4A+6

Результат A+1 мы должны получить для A+1< B  2A+1, результат A+2 – для 2A+2  B  3A+3 и т.д. Таким образом, при B = A+1 мы всегда получаем правильный ответ A+1. Аналогично для B = 2A+2 и B = 2A+3 программа выдаёт правильный ответ A+2. Поэтому для ответа на второй вопрос можно взять, например, пару A = 3 и B = 4:

2) для A = 3 и B = 4 программа выводит правильный ответ 4.

  1. Эта задача очень похожа на предыдущую, поэтому приведём только краткий ответ:


1) при вводе чисел 13 и 18 будет выведено значение 15.

2) для A = 3 и B = 3 программа выводит правильный ответ 4.

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

  1. Неверное начальное значение s:

Было: s := 0;

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

  1. Неверное условие цикла:

Было: while s < B do begin;

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

  1. С помощью трассировки определяем, что при вводе числа 9532 программа выдаёт ответ 32:




A

n2

read(A)

9532




n2 := 0




0

A > 100  да







A mod 100 > n2  да







n2 := A mod 100




32

A := A div 100

95




A > 100  нет







1) при вводе числа 9532 будет выведено значение 32.

При трассировке мы заметили, что пары цифр 53 и 95, которые присутствуют в десятичной записи числа, не проверялись. Во-первых, цикл закончился, когда число стало меньше 100, из-за этого не проверялась пара цифр 95. Поэтому нужно изменить условие цикла на A > 0. Во-вторых, делением на 100 отсекаются сразу две цифры, из-за этого не проверялась пара цифр 53. Поэтому нужно делить не на 100, а на 10.

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

  1. Неверное условие цикла:

Было: while A > 100 do begin

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

  1. Неверное изменение переменной A:

Было: A := A div 100;

Исправление: A := A div 10;

Из проведённого выше анализа видно, что программа выдаст верное значение, если наибольшее двузначное число составляют последние 2 цифры или 3 и 4 цифры с конца, и т.д.

2) программа выводит верное значение 95 при вводе числа 3295.

  1. Эта задача полностью аналогична предыдущей задаче, поэтому приведём только краткий ответ.

1) при вводе числа 1245 будет выведено значение 10.

2) программа ни для одного числа не выводит верное значение (всегда выводит 10).

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

  1. Неверное начальное значение переменной n2:

Было: n2 := 10;

Исправление: n2 := 100;

  1. Неверное условие цикла:

Было: while A > 100 do begin

Исправление: while A > 10 do begin

  1. Неверное изменение переменной A:

Было: A := A div 100;

Исправление: A := A div 10;

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

Посмотрим на все действия с переменной sum в программе:
1   ...   10   11   12   13   14   15   16   17   18


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