NWD - Algorytm Euklidesa na Maturze z Informatyki
Algorytm Euklidesa to fundamentalny algorytm służący do obliczania NWD (Największego Wspólnego Dzielnika) dwóch liczb. Na maturze z informatyki pojawia się bardzo często - zarówno w formie bezpośredniej ('oblicz NWD'), jak i jako element większych zadań algorytmicznych. Jest to jeden z najstarszych algorytmów w historii matematyki (opisany ok. 300 p.n.e.), ale wciąż najskuteczniejszy do tego celu.
Dlaczego to ważne? NWD pojawia się w zadaniach dotyczących skracania ułamków, znajdowania wspólnych dzielników, analizy podzielności liczb i wielu innych. Opanowanie algorytmu Euklidesa to absolutna podstawa na maturze rozszerzonej. W latach 2022-2025 pojawił się w co najmniej jednym zadaniu na każdym arkuszu.
Teoria
Algorytm Euklidesa opiera się na prostej obserwacji: NWD(a, b) = NWD(b, a mod b). Innymi słowy, największy wspólny dzielnik dwóch liczb jest taki sam jak największy wspólny dzielnik mniejszej liczby i reszty z dzielenia większej przez mniejszą. Proces powtarzamy, aż reszta wyniesie 0.
Jak to działa?
- Mamy dwie liczby a i b (załóżmy, że a ≥ b)
- Obliczamy resztę z dzielenia: r = a mod b (operator % w Pythonie i C++)
- Jeśli r = 0, to NWD(a, b) = b - kończymy algorytm
- Jeśli r ≠ 0, to podstawiamy: a → b, b → r i wracamy do kroku 2
- Powtarzamy proces aż reszta wyniesie 0
Złożoność: Złożoność czasowa: O(log min(a, b)) - bardzo szybki algorytm nawet dla dużych liczb. Dla liczb rzędu miliona wykonuje maksymalnie około 20 operacji.
Implementacja
Wersja iteracyjna (najprostsza i najczęściej używana)
Pythondef nwd(a, b):
while b != 0:
a, b = b, a % b
return a
# Przykłady użycia
print(nwd(48, 18)) # Wynik: 6
print(nwd(100, 35)) # Wynik: 5
print(nwd(17, 19)) # Wynik: 1 (liczby względnie pierwsze)
print(nwd(1000, 500))# Wynik: 500Najprostsza i najczęściej używana wersja. Pętla while działa dopóki b nie wyniesie 0. W każdej iteracji zamieniamy miejscami liczby: nowe a staje się starym b (a → b), a nowe b to reszta z dzielenia (b → a % b). Python pozwala na elegancką zamianę miejsc w jednej linii: a, b = b, a % b.
Wersja rekurencyjna (krótsza)
Pythondef nwd_rekurencja(a, b):
if b == 0:
return a
return nwd_rekurencja(b, a % b)
# Przykład użycia
print(nwd_rekurencja(48, 18)) # Wynik: 6
print(nwd_rekurencja(100, 35)) # Wynik: 5Elegancka wersja rekurencyjna - funkcja wywołuje samą siebie z nowymi parametrami, aż b osiągnie 0. Jest krótsza do napisania, ale dla bardzo dużych liczb może być ryzyko przepełnienia stosu wywołań (w praktyce na maturze to nie problem).
Wersja iteracyjna C++
C++#include <iostream>
using namespace std;
int nwd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
cout << nwd(48, 18) << endl; // Wynik: 6
cout << nwd(100, 35) << endl; // Wynik: 5
cout << nwd(17, 19) << endl; // Wynik: 1
return 0;
}W C++ musimy użyć zmiennej tymczasowej temp, bo nie mamy wygodnej zamiany miejsc jak w Pythonie. Zapisujemy b do temp, potem obliczamy nowe b (reszta z dzielenia), a następnie podstawiamy temp (stare b) do a.
Wersja rekurencyjna C++
C++#include <iostream>
using namespace std;
int nwd(int a, int b) {
if (b == 0) return a;
return nwd(b, a % b);
}
int main() {
cout << nwd(48, 18) << endl; // Wynik: 6
cout << nwd(100, 35) << endl; // Wynik: 5
return 0;
}Wersja rekurencyjna jest krótsza i bardziej elegancka w C++. Całą logikę można zapisać w 2 liniach. Dla matury obie wersje (iteracyjna i rekurencyjna) są równie dobre.
Przykładowe Zadania Maturalne
W pliku 'pary.txt' znajduje się 200 wierszy. Każdy wiersz zawiera dwie dodatnie liczby całkowite 'a' i 'b', oddzielone spacją. Napisz program, który policzy, ile z tych par to liczby względnie pierwsze. Dwie liczby są względnie pierwsze, jeśli ich największy wspólny dzielnik (NWD) jest równy 1.
Wskazówka: Musisz wczytać każdą parę (a, b) z pliku. Dla każdej pary oblicz NWD(a, b) za pomocą algorytmu Euklidesa. Jeśli wynik tego obliczenia to 1, zwiększ licznik.
Pokaż szkic rozwiązania
1. Zdefiniuj funkcję nwd(a, b), która implementuje algorytm Euklidesa.
2. Otwórz plik 'pary.txt' do odczytu.
3. Zainicjuj zmienną 'licznik_wzglednie_pierwszych = 0'.
4. Dla każdej linii w pliku:
a. Wczytaj linię, podziel ją na dwie liczby 'a' i 'b'.
b. Oblicz 'wynik_nwd = nwd(a, b)'.
c. Jeśli 'wynik_nwd == 1':
i. 'licznik_wzglednie_pierwszych = licznik_wzglednie_pierwszych + 1'.
5. Po przejściu całej pętli, wypisz wartość 'licznik_wzglednie_pierwszych'.W pliku dron.txt znajduje się 100 wierszy, w których zapisano dane dotyczące ruchu drona. W każdym wierszu jest zapisana para liczb całkowitych [A, B] rozdzielonych znakiem spacji. Dla każdego przesunięcia [A, B] zapisanego w pliku dron.txt oblicz największy wspólny dzielnik (NWD) wartości bezwzględnych liczb A i B. Podaj liczbę par [A, B], dla których największy wspólny dzielnik wartości bezwzględnych liczb A i B jest większy od 1. Uwaga: przyjmujemy, że NWD(A,0)=A.
Wskazówka: Musisz wczytać każdą linię z pliku, podzielić ją na dwie liczby A i B. Pamiętaj o użyciu wartości bezwzględnych (np. abs(A) i abs(B)), a następnie dla każdej pary oblicz NWD. Jeśli wynik jest większy od 1, zwiększ licznik.
Pokaż szkic rozwiązania
1. Zdefiniuj funkcję nwd(a, b), która implementuje algorytm Euklidesa.
2. Otwórz plik 'dron.txt' do odczytu.
3. Zainicjuj zmienną 'licznik_par = 0'.
4. Dla każdej linii w pliku:
a. Wczytaj linię, podziel ją na dwie liczby 'a' i 'b'.
b. Oblicz 'a_abs = abs(a)' oraz 'b_abs = abs(b)'.
c. Oblicz 'wynik_nwd = nwd(a_abs, b_abs)'.
d. Jeśli 'wynik_nwd > 1':
i. 'licznik_par = licznik_par + 1'.
5. Po przejściu całej pętli, wypisz wartość 'licznik_par'.Częste Błędy
❌ Dzielenie przez zero
Jeśli nie sprawdzisz warunku b != 0 w pętli lub b == 0 w rekurencji, program spróbuje wykonać a % 0, co wywoła błąd dzielenia przez zero.
Poprawka: Zawsze sprawdzaj warunek stopu: while b != 0 (iteracja) lub if b == 0: return a (rekurencja). To jest kluczowy warunek algorytmu.
❌ Nieprawidłowa kolejność argumentów
Niektórzy uczniowie myślą, że pierwsza liczba MUSI być większa. To nieprawda - algorytm działa zawsze, ale jeśli a < b, pierwsza iteracja automatycznie je zamieni.
Poprawka: Nie musisz sprawdzać czy a > b. Algorytm sam się tego 'domyśli' w pierwszej iteracji. Ale jeśli chcesz, możesz dodać: if a < b: a, b = b, a
❌ Używanie odejmowania zamiast modulo
Istnieje wersja algorytmu Euklidesa oparta na odejmowaniu (a = a - b zamiast a = a % b), ale jest znacznie wolniejsza. Dla liczb 1000000 i 1 wykona się milion razy zamiast ~20.
Poprawka: ZAWSZE używaj operatora modulo (%). To kluczowa optymalizacja, która sprawia, że algorytm jest O(log n) zamiast O(n).
❌ Zapomnienie o zwróceniu wyniku
W rekurencji musisz ZWRÓCIĆ wynik rekurencyjnego wywołania: return nwd(b, a % b), a nie tylko nwd(b, a % b).
Poprawka: Pamiętaj o słowie kluczowym return przed wywołaniem rekurencyjnym.
❌ Błąd przy obliczaniu NWW z NWD
Wzór na NWW to NWW(a,b) = (a*b)/NWD(a,b), ale trzeba uważać na kolejność działań i typ dzielenia.
Poprawka: W Pythonie użyj // (dzielenie całkowite): nww = (a * b) // nwd(a, b). W C++ wystarczy / bo typ int automatycznie obetnie część ułamkową.
Kluczowe Wnioski
- Algorytm Euklidesa to najszybszy sposób obliczania NWD - złożoność O(log n)
- Dwie główne wersje: iteracyjna (bezpieczniejsza) i rekurencyjna (krótsza)
- Kluczowa operacja: a mod b (reszta z dzielenia), oznaczana jako % w Python i C++
- Warunek stopu: algorytm kończy się gdy b = 0, wtedy NWD = a
- NWD(a, b) = 1 oznacza, że liczby są względnie pierwsze
- Z NWD można łatwo obliczyć NWW: NWW(a,b) = (a*b) / NWD(a,b)
- Algorytm działa niezależnie od kolejności argumentów (sam się 'naprawi')
Najczęściej Zadawane Pytania
❓ Czy mogę używać wbudowanej funkcji math.gcd() w Pythonie na maturze?
Na maturze możesz używać biblioteki standardowej, więc math.gcd() jest dozwolone. JEDNAK w wielu zadaniach jest wprost napisane 'napisz funkcję obliczającą NWD', co oznacza, że musisz zaimplementować algorytm sam. Bezpieczniej jest umieć napisać go z pamięci.
❓ Która wersja jest lepsza - iteracyjna czy rekurencyjna?
Dla matury obie są równie dobre i dostajesz pełne punkty. Iteracyjna jest bezpieczniejsza (brak ryzyka przepełnienia stosu dla bardzo dużych liczb), ale rekurencyjna jest krótsza do napisania (3 linijki kodu). Wybierz tę, którą lepiej rozumiesz i pamiętasz.
❓ Co zrobić jeśli jedna z liczb to 0?
Z definicji matematycznej NWD(a, 0) = a (dla a > 0), bo każda liczba dzieli 0. Algorytm Euklidesa obsługuje ten przypadek automatycznie - jeśli b = 0 na starcie, pętla/rekurencja się od razu kończy i zwracamy a. Potwierdza to np. zadanie 3.1 z matury Maj 2025.
❓ Czy muszę sprawdzać czy pierwsza liczba jest większa od drugiej?
Nie musisz. Jeśli a < b, to już pierwsza iteracja automatycznie zamieni je miejscami. Po pierwszym kroku a stanie się większe. Algorytm działa poprawnie niezależnie od kolejności argumentów.
❓ Jak szybko działa algorytm Euklidesa?
Bardzo szybko! Złożoność to O(log min(a,b)). Dla liczb rzędu miliona wykona się maksymalnie około 20 iteracji. To jeden z najszybszych algorytmów w informatyce.
Chcesz opanować wszystkie tematy maturalne?
Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.