11.07.2015 Views

Выпуск 1 - Российский государственный профессионально ...

Выпуск 1 - Российский государственный профессионально ...

Выпуск 1 - Российский государственный профессионально ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

ПРОФИЛЬответственно, что и требовалось доказать. Поэтомуприведенная программа — правильная.Пример 3. Попробуем доказать или опровергнутьправильность уже встречавшейся ранее программыдля выбора максимального из трех значений,записанных в переменных a, b и c:если a > b то M:= a иначе M:= b все | 1если b > c то M:= b иначе M:= c все | 2Анализируя строку 2, выясняем, что в ней значениепеременной M всегда будет изменено, то есть результатработы первой строки программы стирается, и⎧b,b > cM = ⎨⎩ c , c ≥ bКонечно, эта величина не совпадает с определениеммаксимального значения из a, b и c. Такимобразом, программа неправильная: она выдает неверноезначение, если максимальное из трех чиселхранилось в переменной a. Контрпример мы ужеприводили: (3,2,1).что условие НОД(a, b) = НОД(m, n) по-прежнемувыполняется после каждого шага цикла.Поскольку остаток r с каждым шагом строгоуменьшается, в конце концов он станет равнымнулю и запишется в переменную b при выполнениистроки 4. Цикл сразу же закончится, поскольку нарушаетсяусловие его выполнения. После завершенияработы цикла условие НОД(a, b) = НОД(m, n)по-прежнему выполняется, но, кроме того, b = 0.Отсюда следует, что a = НОД(m, n).Инвариант циклаТаким образом, для алгоритма Евклида существуетусловие НОД(a, b) = НОД(m, n), которое остаетсясправедливым на протяжении всего выполненияалгоритма: перед началом цикла, после каждогошага цикла и после окончания работы цикла. Такоеусловие называется инвариантом цикла (англ.invariant — неизменный).18январь 2012 / ИНФорматикаАлгоритм ЕвклидаТеперь докажем, что один из древнейших известныхалгоритмов — алгоритм Евклида — действительновычисляет наибольший общий делитель(НОД) двух натуральных чисел (мы рассматривалиего в 10-м классе).Алгоритм Евклида. Пусть заданы два натуральныхчисла m и n, причем m > n. Для вычисленияНОД(m, n) следует многократно заменять большеечисло остатком от деления большего на меньшее дотех пор, пока меньшее число не станет равным нулю.Тогда оставшееся ненулевое число и есть НОД(m, n).Программа, основанная на алгоритме Евклида,может выглядеть, например, так (здесь a, b и r —целочисленные переменные):a:= m; b:= n | 1 НОД(a,b) = НОД(m,n)нц пока b 0 | 2r:= mod(a, b) | 3a:= b; b:= r | 4 НОД(a,b) = НОД(m,n)кц | 5вывод a | 6 НОД(a,b) = НОД(m,n), b = 0Докажем, что в результате этого алгоритма в переменнойa находится НОД(m, n).В строке 1 исходные значения копируются изпеременных m и n соответственно в переменныеa и b. Очевидно, что при этом выполнено условиеНОД(a, b) = НОД(m, n).На каждом шаге цикла (в строках 3–4) вычисляетсяостаток r от деления a на b, и пара (a, b) заменяетсяна пару (b, r). Какими свойствами обладаютполученные значения b и r?Поскольку r — это остаток от деления a наb, до выполнения строк 3–4 было справедливоравенство a = bp + r, где p — некоторое целоечисло. Тогда, если a и b имеют общий делитель,то такой же делитель имеет и r. Следовательно,НОД(b, r) = НОД(a, b) = НОД(m, n). Это значит,Инвариант цикла — это соотношение между значениямипеременных, которое остается справедливымпосле завершения любого шага цикла.Как мы увидели, выделение инварианта циклав явном виде очень важно для доказательстваправильности программы. Поэтому полезно задумыватьсяоб инварианте уже при разработке циклическихалгоритмов. Таким образом, мы делаемпервый шаг к доказательству их правильности иизбегаем многих возможных ошибок на начальнойстадии. Как писал академик А.П. Ершов, одиниз первых теоретиков программирования в СССР,“программиста бьют по рукам, если он посмеет написатьоператор цикла, не найдя перед этим егоинварианта”.Рассмотрим несколько примеров.Пример 1. Двое играют в следующую игру: передними лежат в ряд N + 1 камней, сначала N белых,и в конце цепочки — один черный. За один ходкаждый может взять от 1 до 3 камней. Проигрываеттот, кто берет черный (“несчастливый”) камень.Начнем анализ с простейших случаев. ЕслиN = 0, то первый игрок проиграл, он может взятьтолько черный камень. Если N = 1, 2, 3, то, наоборот,при правильной игре проигрывает второйигрок, потому что первый может забрать все камни,кроме черного. Вариант N = 4 снова приводит кпроигрышу первого, потому что забрать все белыекамни он не может, а после его хода второй оставиттолько черный камень. Также проигрышными будутпозиции при N = 8, 12, 16, …, то есть при любыхзначениях N, которые делятся на 4.Таким образом, для своего выигрыша игрок долженкаждым своим ходом восстанавливать инвариант:число оставшихся белых камней должно бытькратно 4. Если инвариант выполнен в начальнойпозиции, положение проигрышное и первый игрок

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!