Опубликован: 08.04.2009 | Доступ: свободный | Студентов: 485 / 0 | Длительность: 17:26:00
Специальности: Программист
Лекция 1:

Переменные, выражения, присваивания

1.1.15. Даны натуральные a и b, не равные 0 одновременно. Найти d = НОД(a,b) и такие целые x и y, что d = a\cdot x + b\cdot y.

Решение. Добавим в алгоритм Евклида переменные p, q, r, s и впишем в инвариант условия m = p*a+q*b ; n = r*a+s*b.

m:=a; n:=b; p := 1; q := 0; r := 0; s := 1; 
{инвариант: НОД (a,b) = НОД (m,n); m,n >= 0 
    m = p*a + q*b; n = r*a + s*b.} 
while not ((m=0) or (n=0)) do begin 
| if m >= n then begin 
| | m := m - n; p := p - r; q := q - s; 
| end else begin 
| | n := n - m; r := r - p; s := s - q; 
| end; 
end; 
if m = 0 then begin 
| k :=n; x := r; y := s; 
end else begin 
| k := m; x := p; y := q; 
end;

1.1.16.Решить предыдущую задачу, используя в алгоритме Евклида деление с остатком.

1.1.17. (Э. Дейкстра) Добавим в алгоритм Евклида дополнительные переменные u, v, z:

m := a; n := b; u := b; v := a; 
{инвариант: НОД (a,b) = НОД (m,n); m,n >= 0 } 
while not ((m=0) or (n=0)) do begin 
| if m >= n then begin 
| | m := m - n; v := v + u; 
| end else begin 
| | n := n - m; u := u + v; 
| end; 
end; 
if m = 0 then begin 
| z:= v; 
end else begin {n=0} 
| z:= u; 
end;

Доказать, что после исполнения алгоритма значение z равно удвоенному наименьшему общему кратному чисел a, b: z = 2\cdot НОК(a,b).

Решение. Заметим, что величина m\cdot u + 
n\cdot v не меняется в ходе выполнения алгоритма. Остается воспользоваться тем, что вначале она равна 2ab и что НОД (a,b) \cdot НОК (a, b) = ab.

1.1.18. Написать вариант алгоритма Евклида, использующий соотношения

\begin{multiple} 
НОД}(2}a}, 2}b})=2}\cdotНОД}(a},b}), \\ 
НОД}(2}a},b})= НОД}(a},b}) \quad 
\text {при нечетном b}}, 
\end{multiple}}

не включающий деления с остатком, а использующий лишь деление на 2 и проверку четности. (Число действий должно быть порядка log k для исходных данных, не превосходящих k.)

Решение.

m:= a; n:=b; d:=1; 
 {НОД(a,b) = d * НОД(m,n)} 
 while not ((m=0) or (n=0)) do begin 
 | if (m mod 2 = 0) and (n mod 2 = 0) then begin 
 | | d:= d*2; m:= m div 2; n:= n div 2; 
 | end else if (m mod 2 = 0) and (n mod 2 = 1) then begin 
 | | m:= m div 2; 
 | end else if(m mod 2 = 1) and (n mod 2 = 0) then begin 
 | | n:= n div 2; 
 | end else if (m mod 2=1) and (n mod 2=1) and (m>=n) then begin 
 | | m:= m-n; 
 | end else if (m mod 2=1) and (n mod 2=1) and (m<=n) then begin 
 | | n:= n-m; 
 | end; 
 end; 
 {m=0 => ответ=d*n; n=0 => ответ=d*m}

Оценка числа действий: каждое второе действие делит хотя бы одно из чисел m и n пополам.

1.1.19. Дополнить алгоритм предыдущей задачи поиском x и y, для которых ax+by=НОД(a,b).

Решение. (Идея сообщена Д. Звонкиным.) Прежде всего заметим, что одновременное деление a и b пополам не меняет искомых x и y. Поэтому можно считать, что с самого начала одно из чисел a и b нечетно. (Это свойство будет сохраняться и далее.)

Теперь попытаемся, как и раньше, хранить такие числа p,q,r,s, что

\begin{align*} 
m =ap + bq,\\ 
n =ar + bs. 
\end{align*}
Проблема в том, что при делении, скажем, m на 2 надо разделить p и q на 2, и они перестанут быть целыми (а станут двоично-рациональными). Двоично-рациональное число естественно хранить в виде пары \langle числитель, показатель степени двойки в знаменателе \rangle. В итоге мы получаем d в виде комбинации a и b с двоично-рациональными коэффициентами. Иными словами, мы имеем
2^{i}d = ax + by
для некоторых целых x,y и натурального i. Что делать, если i > 1? Если x и y четны, то на 2 можно сократить. Если это не так, положение можно исправить преобразованием
\begin{align*} 
x\mathbin:=x + b,  \\ 
y\mathbin:=y - a 
\end{align*}
(оно не меняет ax+by ). Убедимся в этом. Напомним, что мы считаем, что одно из чисел a и b нечетно. Пусть это будет a. Если при этом y четно, то и x должно быть четным (иначе ax+by будет нечетным). А при нечетном y вычитание из него нечетного a делает y четным.