Zastosowanie algorytmu Euklidesa Przelewanie wody Dysponujesz dwoma czerpakami o pojemnościach 4 i 6 litrów, pustym pojemnikiem o nieograniczonej objętości i nieograniczoną ilością wody. Podaj sposób napełnienia pojemnika 14. litrami wody, przy czym wodę możesz wlewać do pojemnika lub wylewać z niego tylko pełnymi czerpakami. Rozwiązanie: [0,0,0] -> [4,0,0] -> [0,0,4] -> [4,0,4] -> [0,0,8] -> [0,6,8] -> [0,0,14] Czyli znaleźliśmy rozwiązanie po 6 ruchach. Uogólniając pytamy, czy dla każdych wartości pojemności czerpaków i pojemnika istnieje rozwiązanie? Przyjmijmy, że czerpaki moją odpowiednio pojemności m oraz n. Natomiast pojemnik ma wartość k. Szukamy wówczas rozwiązania równania: m*x + n*y = k (*) gdzie x i y to liczby całkowite określające ilość przelewań czerpakami m oraz n. Szukaliśmy rozwiązania równania: 4*x + 6*y = 14 Łatwo zaobserwować, że powyższe równanie ma rozwiązanie, ale gdyby pojemnik miał zawierać 15 litrów, wówczas równanie 4*x + 6*y = 15 nie posiadałoby rozwiązania. Wniosek: Dla zadanych m,n i k równanie (*) ma rozwiązanie x i y tylko wtedy, gdy k jest równe NWD(m,n), lub jest jego wielokrotnością. Przyjrzyjmy się algorytmowi Euklidesa. Załóżmy, że n<=m. Gdy n podzielimy przez m, otrzymamy następującą równość: n = q*m + r gdzie r – reszta, 0<=r<m (**) q i r są odpowiednio ilorazem i resztą. Najistotniejszy wniosek, pozwalający na znalezienie NWD opiera się dalej na podstawieniu: NWD(m,n)=NWD(r,m) Np. m=46, n=48: Z równania (**) mamy: 48=1*46+2 r=2 46=23*2+0 NWD(46,48)=NWD(2,46)=NWD(0,2), czyli NWD(46,48)=2 Prześledźmy znajdowanie NWD na następnym przykładzie: m=12, n=21. Stosując równanie (**) znajdujemy najpierw NWD: 21 = 1*12 + 9 (1) 12 = 1 *9 + 3 (2) 9 = 3*3 + 0 (3) Stąd NWD(12,21)=3 Aby otrzymać równość (*) dokonajmy przekształceń powyższego rozwiązania: Z (2): 12 – 1*9 = 3 Z (1): 9 = 21 – 1*12 Podstawiamy 1 do 2: 12 – 1*(21-1*12) = 3 2*12-1*21 = 3 a więc 2*m-1*n = 3 Można zapisać w postaci iteracji kolejne kroki algorytmu Euklidesa: a0=q1*a1+a2 a1=q2*a2+a3 . . . al+1=ql*al+al+1 gdzie przyjęliśmy: a0=n, a1=m oraz al.+1=0, czyli al=NWD(m,n). Szukamy zatem rozwiązania równania: NWD(m,n)=mx+ny. W tym celu algorytm będzie tworzył również dwa podciągi liczb x0,x1, … ,xl oraz y0,y1,…,yl spełniające równość: ai=mxi+nyi dla i=0,1,2,…,l (***) Czyli dla i=l otrzymamy: al=NWD(m,n)=mxl+nyl. Zatem po zakończeniu algorytmu, końcowe wartości elementów ciągów ai, xi oraz yi będą stanowić rozwiązanie równania : mx+ny=k Określmy teraz sposób wyznaczenia elementów ciągów xi oraz yi. Z dwóch pierwszych iteracji algorytmu Euklidesa otrzymamy ich początkowe wartości: n = a0 = mx0 + ny0 czyli x0 = 0, y0 = 1, m = a1 = mx1+ny1 czyli x1 = 1, y1 = 0 Natomiast, gdy skorzystamy z równości ,w algorytmie Euklidesa ai+1=ai-1-qiai i wstawimy do niej wartości ai-1 oraz ai wówczas otrzymamy: ai+1 = ai-1 – qiai = mxi-1 + nyi-1 – qi(mxi + nyi) = = m(xi-1 – qixi) + n(yi-1 – qiyi) Porównując równanie z zależnością (***) dla i+1 stwierdzimy: xi+1 = xi-1-qixi oraz yi+1 = yi-1 - qiyi To kończy definiowanie ai, xi, yi. W tabeli przedstawione są wartości kolejnych elementów tych ciągów dla przykładu: m=12 oraz n=21. m= 12 i 0 1 2 3 4 n= 21 a[i] 21 12 9 3 0 q[i] 1 1 3 x[i] 0 1 -1 2 y[i] 1 0 1 -1 Algorytm Euklidesa – wersja rozszerzona: Dane: Wyniki: Dwie liczby naturalne m i n, m<=n Największy wspólny dzielnik m i n, NWD(m,n) oraz rozwiązanie r-nia: xm+yn=k, gdzie k=NWD(m,n) Krok 1. {Przypisanie wartości początkowych} a=n; a’=m; x=0; y=1; x’=1; y’=0 Krok 2. Jeśli a’==0, to a=NWD(m,n) oraz x i y stanowią rozwiązanie r-nia: x*m+y*n=k, gdzie k=NWD(m,n) – zakończ algorytm Krok 3. Wykonaj przypisania: q = a div a’; {div – dzielenie całkowite bez reszty} temp=a’; a’=a – q*a’; a=temp; {temp – zmienna pomocnicza} temp=x’; x’=x – q*x’; x=temp; temp=y’; y’=y – q*y’; a=temp; Krok 4. Wróć do kroku 2. Działania na ułamkach. Do naszych działań przyjmujemy ułamek zwykły postaci p/q, gdzie p i q są liczbami względnie pierwszymi oraz q>0. Podstawowe działania arytmetyczne na ułamkach zwykłych: p p' p ⋅ q'± p'⋅q ± = ; q q' q ⋅ q' p p' p ⋅ p' ; ⋅ = q q' q ⋅ q' p p ' p ⋅ q' : = q q' q ⋅ p ' Aby wyniki tych działań były również ułamkami zwykłymi, należy skrócić ułamki występujące po prawej stronie tożsamości, gdy to jest możliwe. W programie komputerowym skracanie ułamków przeprowadzamy w trakcie wykonywania obliczeń, a nie na końcu. Dzięki temu unikamy dużych liczb w trakcie obliczeń. W trakcie działań przydatna może być funkcja NWW(m,n) – najmniejsza wspólna wielokrotność. Najmniejszą wspólną wielokrotnością liczb naturalnych m i n jest najmniejsza liczba naturalna, która dzieli się przez m i n. Oznaczamy ją NWW(m,n). Prawdziwy jest związek: NWW ( m, n ) = m⋅n NWD( m, n ) Aby uniknąć dużego licznika w wyrażeniu na NWW, możemy go także przedstawić w postaci: NWW ( m, n ) = m n NWD( m, n ) Algorytm obliczania najmniejszej wspólnej wielokrotności dwóch liczb. Dane: Wyniki: Dwie liczby naturalne m i n, m<=n. NWW(m,n). Krok 1. Krok 2. Oblicz NWD(m,n) {Zastosuj w tym celu algorytm Euklidesa} NWW(m,n) jest równa m*(n div NWD(m,n)). Dodawanie ułamków (odejmowanie będzie wyglądało podobnie). Obliczamy najpierw r=NWD(q,q’). Jeśli r=1, to wyniku dodawania nie można skrócić. Jeśli r>1, to obliczamy ⎛q⎞ ⎛ q' ⎞ t = p⎜ ⎟ + p' ⎜ ⎟ ⎝r⎠ ⎝r⎠ s = NWD(t , r ) Wówczas: p p' p ⋅ q'+ p'⋅q t/s + = = q q' q ⋅ q' (( q / r )( q' / s )) Sprawdźmy na przykładzie. - metodą tradycyjną: 15 19 180 + 988 1168 73 + = = = 52 12 624 624 39 - metodą opisaną powyżej: r=NWD(52,12)=4, t=15*3+19*13=292, s=NWD(292,4)=4. Stąd, 15 19 ( 294 / 4) 73 + = = 52 12 ((52 / 4)(12 / 4)) 39 Jak widać w drugim przypadku wystąpiły mniejsze liczby w trakcie obliczeń. Mnożenie i dzielenie ułamków. Ponieważ p i q oraz p’ i q’ są parami liczb względnie pierwszych, mamy więc NWD(pp’,qq’)=rs, gdzie r=NWD(p,q’) i s=NWD(q,p’). Wynika stąd: p p' p ⋅ p' ( p / r )( p' / s ) ⋅ = = q q' q ⋅ q' (q / s )(q' / r ) Podobnie z dzieleniem: r=NWD(p,p’) i s=NWD(q.q’). Wówczas przy spełnieniu warunku p’>0: p p' p ⋅ q' ( p / r )(q' / s ) : = = q q' p'⋅q (q / s )( p' / r ) Literatura: Algorytmy – M. M. Sysło wyd. WSiP