Главная / Программирование /
Основы программирования - обучения основам / Тест 5
Основы программирования - обучения основам - тест 5
Упражнение 1:
Номер 1
Рассмотрим следующий фрагмент программы:
утверждение: A(x)
цикл пока B(x)
| инвариант: A(x)
| x := T(x)
конец цикла
Здесь через A(x)
и B(x)
обозначены условия, зависящие от переменной x
.
Какое условие выполняется по окончании цикла?
Ответ:
 (1)
Условие (не A(x) и B(x))
.
 
 (2)
Условие (A(x) и B(x))
.
 
 (3)
Условие (A(x) и не B(x))
.
 
Номер 2
Выполняется ли инвариант цикла в процессе выполнения
тела цикла?
Ответ:
 (1)
Да, выполняется.
 
 (2)
Не обязательно.
 
Номер 3
Укажите, в какие моменты работы программы выполняется
инвариант цикла.
Ответ:
 (1)
Перед первым выполнением тела цикла и после
последнего выполнения тела цикла.
 
 (2)
Перед каждым выполнением тела цикла.
 
 (3)
Перед каждым выполнением тела цикла и после
каждого выполнения тела цикла.
 
Упражнение 2:
Номер 1
Указать, что вычисляет следующий фрагмент программы:
дано: цел n;
цел s, k;
s := 2; k := 0;
цикл пока s <= n
| инвариант: s = 2k+1
| s := s * 2; k := k + 1;
конец цикла
ответ := k;
Ответ:
 (1)
Целую часть квадратного корня из n
.
 
 (2)
Целую часть от log2 n
.
 
Номер 2
Указать, что вычисляет следующий фрагмент программы:
дано: цел n;
цел x, y;
x := 1; y := 4;
цикл пока y <= n
| инвариант: y = (x + 1)2;
| x := x + 1;
| y := y + 2*x + 1;
конец цикла
ответ := x;
Ответ:
 (1)
Целую часть от n / 2
;
 
 (2)
Целую часть квадратного корня из n
.
 
 (3)
Целую часть от log2 n
.
 
Номер 3
Указать, что вычисляет следующий фрагмент программы:
дано: цел n;
цел s, k;
s := 10; k := 0;
цикл пока s <= n
| инвариант: s = 10 * (k + 1)
| s := s + 10; k := k + 1;
конец цикла
ответ := k;
Ответ:
 (1)
Целую часть частного n/10
.
 
 (2)
Произведение 10·n
.
 
 (3)
Целую часть десятичного логарифма log10 n
.
 
Упражнение 3:
Номер 1
Рассмотрим следующий фрагмент программы:
цел m, n;
цел a, b, p;
. . .
a := m; b := n;
p := 0;
цикл пока b != 0
| если b четное
| | то
| | b := b / 2;
| | a := a * 2;
| | иначе
| | b := b - 1;
| | p := p + a;
| конец если
конец цикла
ответ := p;
Какое условие является инвариантом цикла?
Ответ:
 (1)
Равенство ab p = mn
.
 
 (2)
Равенство a b + p = m n
.
 
Номер 2
Рассмотрим следующий фрагмент программы:
цел m, n;
. . .
дано: m >= 0 и n >= 0
цел a, b, c;
a := m; b := n;
c := 1;
цикл пока a != 0 и b != 0
| если a четное и b четное
| | то a := a / 2;
| | b := b / 2;
| | c := c * 2;
| иначе если a четное
| | то a := a / 2;
| иначе если b четное
| | то b := b / 2;
| иначе
| | если a > b
| | | то a := a - b;
| | | иначе b := b - a;
| | конец если
| конец если
конец цикла
ответ := c * (a + b);
Какое условие является инвариантом цикла?
(Через НОД и НОК обозначены наибольший общий делитель и
наименьшее общее кратное.)
Ответ:
 (1)
Равенство НОД(a, b) = НОД(m, n)·c
.
 
 (2)
Равенство НОК(m, n) = c·(a + b)
.
 
 (3)
Равенство НОД(a,b)·c = НОД(m, n)
.
 
Номер 3
Рассмотрим следующий фрагмент программы, вычисляющей
частное q
и остаток r
от деления
целых чисел a
, b
:
дано: целые числа a >= 0, b > 0
цел q, r, e, m;
q := 0; r := a; e := 1; m := b
цикл пока r >= b
| если 2*m <= r
| | то e := e*2; m := m*2;
| иначе если m > r
| | то e := e/2; m := m/2;
| иначе
| | утверждение: m <= r и r < 2*m
| | q := q + e; r := r - m;
| конец если
конец цикла
// q и r -- частное и остаток от деления a на b
Какое условие является инвариантом цикла?
Ответ:
 (1)
Число e
является степенью двойки, а также
выполняются равенства
a - q·b = r
и
m = e·b
.
 
 (2)
Число e
является степенью двойки, а также
выполняются равенства
a - q·m = r
и
m = e·b
.
 
Упражнение 4:
Номер 1
Какое утверждение является инвариантом для следующего
фрагмента программы (т.е. из справедливости утверждения
до выполнения фрагмента программы вытекает справедливость утверждения
после выполнения)? Предполагается, что n
неотрицательно.
вещ r, x; цел n;
. . .
r := r * x * x;
r := r / ((n + 1) * (n + 2));
n := n + 2;
Ответ:
 (1)
Утверждение r = xn / n!
,
где восклицательным знаком обозначен факториал числа n
.
 
 (2)
Утверждение
r = xn / ((n+1)·(n+2))
.
 
Номер 2
Какое утверждение является инвариантом для следующего
фрагмента программы (т.е. из справедливости утверждения
до выполнения фрагмента программы вытекает справедливость утверждения
после выполнения)? Предполагается, что n > 0
.
вещ r, x; цел n;
. . .
r := -r * x;
r := r * n / (n + 1);
n := n + 1;
Ответ:
 (1)
Утверждение
r = (-1)n xn/n!
,
где восклицательным знаком обозначен факториал числа n
.
 
 (2)
Утверждение
r = (-1)n-1 xn/n
.
 
Номер 3
Какое утверждение является инвариантом для следующего
фрагмента программы (т.е. из справедливости утверждения
до выполнения фрагмента программы вытекает справедливость утверждения
после выполнения)? Предполагается, что n
не меньше k
.
Восклицательным знаком обозначается операция вычисления факториала.
цел n, k, c;
. . .
c := c * (n + 1);
c := c/(n + 1 - k);
n := n + 1;
Ответ:
 (1)
Утверждение
c = n! / (k! (n-k)!)
.
 
 (2)
Утверждение
c = (n+k)! / (n! (n-k)!)
.
 
 (3)
Утверждение
c = (k)! / (n! (n-k)!)
.
 
Упражнение 5:
Номер 1
Оценить сверху время работы (т.е. количество
выполнений тела цикла) алгоритма Евклида
вычисления НОД двух целых чисел:
дано: целые числа m, n, хотя бы одно отлично от нуля
надо: вычислить наибольший общий делитель пары (m, n)
цел a, b, r;
a := m; b := n;
цикл пока b != 0
| инвариант: НОД(a, b) == НОД(m, n)
| r := a % b; // находим остаток от деления a на b
| a := b; b := r; // заменяем пару (a, b) на (b, r)
конец цикла
ответ := a;
Ответ:
 (1)
Время работы не больше, чем
C·log2 max(m, n)
,
где C
— некоторая константа
(т.е. время пропорционально количеству цифр в двоичной или
десятичной записи максимального из чисел m
, n
).
 
 (2)
Время работы не больше, чем
C·r
, где C
— некоторая константа,
r
—
квадратный корень из max(m, n)
(т.е. время пропорционально квадратному корню из максимального
числа).
 
 (3)
Время работы не больше, чем
C·max(m, n)
,
где C
— некоторая константа
(т.е. время пропорционально максимальному из чисел m
, n
).
 
Номер 2
Оценить сверху время работы (т.е. количество
выполнений тела цикла) алгоритма быстрого возведения в степень:
дано: основание a и показатель степени n >= 0
надо: вычислить a в степени n
вещ b, p; цел k;
b := a; p := 1.0; k := n;
цикл пока k > 0
| инвариант: bk p = an
| если k четное
| | то
| | k := k / 2;
| | b := b * b;
| | иначе
| | k := k - 1;
| | p := p * b;
| конец если
конец цикла
ответ := p;
Ответ:
 (1)
Время работы не больше, чем
C·n
,
где C
— некоторая константа
(т.е. время пропорционально числу n
).
 
 (2)
Время работы не больше, чем
C·log2 n
,
где C
— некоторая константа
(т.е. время пропорционально количеству цифр в двоичной или
десятичной записи числа n
).
 
 (3)
Время работы не больше, чем
C·r
, где C
— некоторая константа,
r
— квадратный корень из числа n
(т.е. время пропорционально квадратному корню из n
).
 
Номер 3
Оценить сверху время работы (т.е. количество
выполнений тела цикла) алгоритма
приблизительного вычисления логарифма:
дано: x > 0, a > 1, ε > 0
надо: вычислить loga x с точностью ε
вещ y, z, t;
y := 0.0; z := x; t := 1.0;
цикл пока |t| >= ε или z <= 1.0/a или z >= a
| инвариант: ay * zt = x
| если z >= a
| | то
| | z := z/a; y := y + t;
| иначе если z <= 1.0/a
| | то
| | z := z*a; y := y - t;
| иначе
| | z := z*z; t := t/2.0;
| конец если
конец цикла
ответ := y;
Ответ:
 (1)
Время работы не больше, чем
C·log2 [x+1]
,
где C
— некоторая константа,
[x+1]
— целая часть числа x+1
(т.е. время пропорционально количеству цифр
в двоичной или десятичной записи
целой части числа x
).
 
 (2)
Время работы не больше, чем
C·log2 [x+1]·log2 (1/ε)
,
где C
— некоторая константа, а квадратные скобки
обозначают целую часть.
Иначе говоря, время пропорционально количеству цифр
в двоичной или десятичной записи
целой части x
, умноженному на требуемое количество значащих
цифр в дробной части результата.
 
 (3)
Время работы не больше, чем
C·log2 [x+1] + log2 (1/ε)
,
где C
— некоторая константа, а квадратные скобки
обозначают целую часть. Иначе говоря,
время пропорционально сумме количества цифр
в двоичной или десятичной записи
целой части x
и требуемого количества значащих
цифр в дробной части результата.
 
Упражнение 6:
Номер 1
Пусть f(x)
— целочисленная функция от целочисленного
аргумента. Определить,
содержит ли следующий фрагмент программы ошибку
(т.е. действительно ли тело цикла сохраняет инвариант):
// Программа корень функции
цел a, b, c;
. . .
утверждение: a < b и f(a) * f(b) <= 0;
// Значения функции на концах отрезка [a,b] разных знаков
цикл пока b - a > 1
| инвариант: f(a) * f(b) <= 0
| // Делим отрезок [a, b] пополам
| c := (a + b) / 2; // c -- целая часть (a+b)/2
| если f(a) * f(c) < 0
| | то b := c; // выбираем левую половину отрезка
| | иначе a := c; // выбираем правую половину отрезка
| конец если
конец цикла
утверждение: a == b - 1 и f(a) * f(b) <= 0;
Ответ:
 (1)
Ошибки нет, фрагмент программы корректный.
 
 (2)
Фрагмент программы содержит ошибку.
 
Номер 2
Пусть a
— целочисленный массив размера n
(индекс элементов меняется от 0 до n-1
),
элементы которого строго возрастают:
a[0] < a[1] <... < a[n-1]
.
Определить, содержит ли следующий фрагмент программы ошибку
(т.е. действительно ли тело цикла сохраняет инвариант):
// Программа Поиск
дано: цел n;
цел a[n]; // a[0] < a[1] < ... < a[n-1]
цел x; // искомый элемент
цел b, e, c;
. . . // рассматриваются исключительные случаи
утверждение: a[0] < x и x <= a[n-1]; // общий случай
b := 0; e := n - 1;
цикл пока e - b > 1
| инвариант: a[b] < x и x <= a[e];
| c := (b + e) / 2; // c -- целая часть (b+e)/2
| если x < a[c]
| | то e := c; // выбираем левую половину отрезка
| | иначе b := c; // выбираем правую половину отрезка
| конец если
конец цикла
утверждение: b == e - 1 и
a[b] < x и x <= a[e];
Ответ:
 (1)
Ошибки нет, фрагмент программы корректный.
 
 (2)
Фрагмент программы содержит ошибку.
 
Номер 3
Пусть a
— вещественный массив размера n
(индекс элементов меняется от 0 до n-1
).
Определить, содержит ли следующий фрагмент программы ошибку
(т.е. действительно ли тело цикла сохраняет инвариант):
// Программа Быстрая сортировка
дано: цел n;
вещ a[n]; // вещественный массив размера n
цел m; // индекс медианы
утверждение: n >= 2 и
0 <= m и m < n;
надо: // разделить массив на три части:
// 1) слева элементы, меньшие медианы;
// 2) в центре медиана;
// 3) справа элементы, большие или равные медиане.
цел i, j, k; вещ t;
i := (-1); j := n;
цикл пока i+1 < m или m < j-1
| инвариант: a[0], a[1], ..., a[i] < a[m] и
| a[m] <= a[j], a[j+1], ..., a[n-1] и
| i < m и m < j
|
| если i+1 < m
| | то
| | если a[i+1] < a[m]
| | | то i := i+1; // расширяем левую часть
| | иначе если j-1 > m
| | | иначе
| | | утверждение: a[i+1] >= a[m];
| | | // меняем местами элементы a[i+1] и a[j-1]
| | | t := a[i+1]; a[i+1] := a[j-1]; a[j-1] := t;
| | | если j-1 == m
| | | | то m := i+1; // новое положение медианы
| | | конец если
| | | j := j-1; // расширяем правую часть
| | конец если
| | иначе
| | утверждение: j-1 > m;
| | . . . // этот случай рассматривается аналогично
| | . . . // случаю i+1 < m
| |
| конец если
конец цикла
утверждение: 0 <= m и m < n и
a[0], a[1], ..., a[m-1] < a[m] и
a[m] <= a[m+1], a[m+2], ..., a[n-1]
Ответ:
 (1)
Ошибки нет, фрагмент программы корректный.
 
 (2)
Фрагмент программы содержит ошибку.