ALGORYTM WYZNACZANIA LICZB NIEPODZIELNYCH PRZEZ

advertisement
WYKŁAD 3 (13 MARZEC 2014)
LICZBY CAŁKOWITE I RZECZYWISTE
Bartosz Łakomy i Dariusz Dobiesz
SPIS TREŚCI:
Liczby parzyste i nieparzyste
 Liczby podzielne lub niepodzielne przez zadane
podzielniki
 NWD – algorytm Euklidesa
 Liczby względnie pierwsze
 Najmniejsza wspólna wielokrotność
 Liczby pierwsze – generacja przez sprawdzanie
podzielności
 Liczby pierwsze – generacja sitem Eratostenesa

LICZBY PARZYSTE I NIEPARZYSTE
Problem:
W przedziale całkowitym <a,b> wyszukaj wszystkie liczby parzyste.
Liczby parzyste:
W wielu algorytmach musimy wygenerować liczby parzyste z zadanego
przedziału <a,b> liczb całkowitych. Aby rozwiązać to zadanie wyznaczymy
pierwszą liczbę w przedziale <a,b>, która spełnia kryterium. Następnie w pętli
sprawdzamy, czy wyznaczona liczba mieści się w przedziale <a,b>. Pętlę
kontynuujemy, aż wygenerowana liczba wyjdzie poza przedział <a,b>.
Ponieważ granice przedziału a i b mogą być dowolnymi liczbami całkowitymi,
musimy najpierw znaleźć najmniejszą liczbę parzystą z przedziału <a,b>.
1. Jeśli a jest parzyste, to najmniejszą liczbą parzystą w tym przedziale będzie
właśnie a.
2. Jeśli a nie jest parzyste, to najmniejszą liczbą parzystą będzie a + 1.
Parzystość a sprawdzimy badając resztę z dzielenia a przez 2.
Jeśli reszta jest zerowa, to a jest liczbą parzystą. Jeśli a nie
jest liczbą parzystą, to:
1. Reszta wynosi 1 dla a > 0
2. Reszta wynosi -1 dla a < 0
Z powyższego wnioskujemy, iż pierwszą liczbę parzystą w
przedziale całkowitym <a,b> otrzymamy następująco:
i=a
Jeśli reszta z dzielenia a przez 2 jest różna od 0, to
zwiększ i o 1.
Następna liczba parzysta jest zawsze o 2 większa.
Podsumowując otrzymujemy algorytm generacji liczb
parzystych w przedziale całkowitym <a,b>:
ALGORYTM GENERACJI LICZB PARZYSTYCH
-Wejście
a – początek przedziału, a ∈ Z
b – koniec przedziału, b ∈ Z, a < b
-Wyjście:
Kolejne liczby parzyste zawarte w przedziale <a,b>
-Zmienna pomocnicza
i – przebiega przez kolejne liczby parzyste w przedziale <a,b>, i ∈ Z
-Lista kroków
K01:
i←a
;obliczamy pierwszą liczbę parzystą
K02:
Jeśli a mod 2 ≠ 0, to i ← i + 1
K03:
Dopóki i ≤ b, wykonuj kroki K03...K04 ;generujemy liczby
w przedziale <a,b>
;wyprowadzamy liczbę parzystą
K04:
Pisz i
K05:
i ← i + 2 ;następna liczba parzysta
K06:
Zakończ
parzyste
PROGRAM
#include <iostream>
using namespace std;
int main()
{
int a,b,i;
cin >> a >> b;
i = a;
if(a % 2) i++;
while(i <= b)
{
cout << i << " ";
i += 2;
}
cout << endl;
return 0;
}
Program spodziewa się w pierwszym
wierszu liczb a i b. W kolejnych
wierszach wyświetla liczby parzyste
zawarte w przedziale <a,b>.
Liczby nieparzyste:
Liczby nieparzyste generujemy w identyczny sposób: wyznaczamy pierwszą
liczbę nieparzystą w przedziale <a,b>, a kolejne są o 2 większe. Jeśli a jest
nieparzyste, to pierwsza liczba nieparzysta jest równa a, w przeciwnym razie
jest o 1 większa.
Poniższy program czyta krańce przedziału a, b i wyświetla wszystkie kolejne
liczby nieparzyste zawarte w tym przedziale.
ZADANIE
Napisz program który spodziewa się w pierwszym
wierszu liczb a i b. W kolejnych wierszach wyświetla
liczby nieparzyste zawarte w przedziale <a,b>.
Analogicznie do poprzedniego zadania.
PROGRAM
#include <iostream>
using namespace std;
int main()
{
int a,b,i;
cin >> a >> b;
i = a;
if(a % 2 == 0) i++;
while(i <= b)
{
cout << i << " ";
i += 2;
}
cout << endl;
return 0;
}
LICZBY PODZIELNE LUB NIEPODZIELNE PRZEZ
ZADANE PODZIELNIKI
Problem nr 1:
W przedziale <a,b> liczb całkowitych wyszukać wszystkie liczby podzielne przez
liczby z zadanego zbioru P.
Generujemy wszystkie kolejne liczby z przedziału <a,b> i sprawdzamy, czy
dzielą się bez reszty przez liczby z zadanego zbioru. Jeśli tak,
wyprowadzamy je na wyjście.
ALGORYTM WYZNACZANIA LICZB PODZIELNYCH
PRZEZ ZADANE CZYNNIKI
Wejście
a – początek przedziału, a ∈ Z
b – koniec przedziału, b ∈ Z, a < b
n – liczba podzielników, n ∈ N
P – tablica, której kolejne elementy są podzielnikami. Elementy ∈ Z. Numeracja
elementów od zera.
Wyjście:
Kolejne liczby z przedziału <a,b> podzielne przez podzielniki w P
Zmienne pomocnicze:
i – przebiega przez kolejne liczby w przedziale <a,b>, i ∈ Z
j – przebiega przez numery kolejnych podzielników w P, j ∈ N
Lista kroków:
K01:
Dla i = a,a+1,...,b wykonuj K02...K03 ;przechodzimy przez kolejne
liczby z przedziału <a,b>
K02:
Dla j = 0,1,...,n-1 wykonuj K03 ;sprawdzamy, czy liczba i dzieli się
przez podzielniki.
K03:
Jeśli i mod P[j] = 0, to:
pisz i
następny obieg pętli K01
;z tablicy P[]. Jeśli tak, wyprowadzamy
i, przerywamy pętlę K02
K04:
Zakończ
PROGRAM
#include <iostream>
using namespace std;
const int MAXP = 1000;
int main()
{
int a,b,i,j,n,P[MAXP];
cin >> a >> b >> n;
for(i = 0; i < n; i++)
cin >> P[i];
for(i = a; i <= b; i++)
for(j = 0; j < n; j++)
if(i % P[j] == 0)
{
cout << i << " ";
break;
}
cout << endl;
return 0;
}
Program spodziewa się w pierwszym
wierszu liczb a i b. W drugim wierszu
należy podać n = 1...1000, a następnie
w n wierszach kolejne podzielniki.
Przykładowe dane:
-100 100
3
5
12
17
LICZBY PODZIELNE LUB NIEPODZIELNE PRZEZ
ZADANE PODZIELNIKI
Problem nr 2:
W przedziale <a,b> liczb całkowitych wyszukać wszystkie liczby niepodzielne
przez żadną z liczb z zadanego zbioru P.
Każdą liczbę sprawdzamy na podzielność przez podzielniki z P. Jeśli któryś z
nich dzieli liczbę, to przechodzimy do następnej liczby w <a,b>. Jeśli żaden
nie dzieli liczby, liczbę wyprowadzamy na wyjście.
ALGORYTM WYZNACZANIA LICZB NIEPODZIELNYCH
PRZEZ ZADANE LICZBY
Wejście
a – początek przedziału, a ∈ Z
b –koniec przedziału, b ∈ Z, a < b
n –liczba podzielników, n ∈ N
P –tablica, której kolejne elementy są podzielnikami. Elementy ∈ Z. Numeracja
elementów od zera.
Wyjście:
Kolejne liczby z przedziału <a,b> niepodzielne przez podzielniki w P.
Zmienne pomocnicze:
i – przebiega przez kolejne liczby w przedziale <a,b>, i ∈ Z
j – przebiega przez indeksy podzielników w P, j ∈ N
Lista kroków:
K01:
Dla i = a,a+1,...,b wykonuj kroki K02...K04
;pętla
przebiegająca przez kolejne liczby z <a,b>
K02:
Dla j = 0,1,...,n-1 wykonuj krok K03 ;pętla sprawdzająca podzielność
przez dzielniki z P
K03:
Jeśli i mod P[j] = 0, to następny obieg pętli K01 ;jeśli jakiś dzielnik
dzieli i, przechodzimy do następnej liczby
K04:
Pisz i ;jeśli żaden dzielnik nie dzieli i, wyprowadzamy je
K05:
Zakończ
PROGRAM
#include <iostream>
using namespace std;
const int MAXP = 1000;
int main()
{
int a,b,i,j,n,P[MAXP];
bool t;
cin >> a >> b >> n;
for(i = 0; i < n; i++) cin >> P[i];
for(i = a; i <= b; i++)
{
t = true;
for(j = 0; j < n; j++)
if(i % P[j] == 0)
{
t = false;
break;
}
if(t) cout << i << " ";
}
cout << endl;
return 0;
}
Program spodziewa się w pierwszym
wierszu liczb a i b. W drugim wierszu
należy podać n = 1...1000, a następnie
w n wierszach kolejne podzielniki.
Przykładowe dane:
-100 100
4
2
3
5
7
NWD – ALGORYTM EUKLIDESA
Problem:
Dla danych dwóch liczb naturalnych a i b znaleźć największą liczbę naturalną c,
która dzieli bez reszty liczbę a i dzieli bez reszty liczbę b.
Liczba c o powyższej własności nosi nazwę NWD – największego wspólnego
dzielnika a i b (ang. GCD – greatest common divisor). NWD znajdujemy za
pomocą znanego algorytmu Euklidesa, będącego jednym z najstarszych
algorytmów, ponieważ pojawił się on w dziele Elementy napisanym przez
Euklidesa około 300 p.n.e. Właściwie Euklides nie podał algorytmu dla liczb,
lecz dla dwóch odcinków. Chodziło w nim o znalezienie wspólnej miary (czyli
odcinka jednostkowego), która mogłaby posłużyć do zmierzenia obu danych
odcinków – wspólna miara odkłada się w każdym z odcinków całkowitą liczbę
razy.
Rozwiązanie 1:
Euklides wykorzystał prosty fakt, iż NWD liczb a i b dzieli również ich różnicę. Zatem od
większej liczby odejmujemy w pętli mniejszą dotąd, aż obie liczby się zrównają. Wynik to
NWD dwóch wyjściowych liczb.
Algorytm Euklidesa
Wejście:
a, b – liczby naturalne, których NWD poszukujemy, a, b ∈ N
Wyjście:
NWD liczb a i b
Lista kroków:
K01:
Dopóki a ≠ b wykonuj krok K02
Jeśli a < b, to b ← b - a
inaczej
a←a-b
zrównają
K02:
K03:
Pisz a
K04:
Zakończ
;od większej liczby odejmujemy mniejszą aż się
;wtedy dowolna z nich jest NWD
Start
Wczytaj a,b
nie
a<b
a -= b
tak
b -= a
Wypisz wynik
koniec
PROGRAM
#include <iostream>
using namespace std;
int main()
{
unsigned int a,b;
cin >> a >> b;
while(a != b)
if(a < b) b -= a; else a -= b;
cout << a << endl;
return 0;
}
Program odczytuje z pierwszego
wiersza dwie liczby a i b, a
następnie wypisuje w następnym
wierszu ich NWD. Żadna z
liczb a i b nie może wynosić 0 –
wtedy różnica nie zmienia
większej z nich i program działa w
nieskończoność.
Zadanie:
Popraw kod z lewej strony tak
żeby 0 nie stanowiło problemu 
#include <iostream>
using namespace std;
int main()
{
unsigned int a,b;
cin >> a >> b;
if ((a==0)||(b==0))
{
cout << "NWD = 0" << endl;
}
while(a != b)
if(a < b) b -= a; else a -= b;
cout << a << endl;
return 0;
}
Rozwiązanie 2:
Pierwsze rozwiązanie problemu znajdowania NWD jest złe z punktu widzenia
efektywności. Wyobraźmy sobie, iż a jest równe 4 miliardy, a b jest równe 2.
Pętla odejmująca będzie wykonywana dotąd, aż zmienna a zrówna się ze
zmienną b, czyli w tym przypadku 2 miliardy razy – trochę dużo. Tymczasem
można wykorzystać operację reszty z dzielenia. Mniejszą liczbę można odjąć
od większej liczby tyle razy, ile wynosi iloraz całkowity tych liczb. Po
odejmowaniu pozostaje reszta z dzielenia – a Euklides właśnie zauważył, iż
NWD dzieli również różnicę danych liczb, czyli:
NWD(a,b) = NWD(a mod b,b)
Ponieważ reszta zawsze jest mniejsza od dzielnika, wymieniamy a z b,
a b z a mod b. Jeśli otrzymamy wynik b = 0, to w a jest ostatni dzielnik
dzielący bez reszty różnicę.
Algorytm Euklidesa
Wejście
a, b – liczby naturalne, których NWD poszukujemy, a, b ∈ N
Wyjście:
NWD liczb a i b
Zmienne pomocnicze
t – tymczasowo przechowuje dzielnik, t ∈ N
Lista kroków:
K01:
Dopóki b ≠ 0 wykonuj kroki K02...K04
K02:
t←b
;zapamiętujemy dzielnik
K03:
b ← a mod b
dzielnikiem
;wyznaczamy resztę z dzielenia, która staje się
K04:
a←t
;poprzedni dzielnik staje teraz się dzielną
K05:
Pisz a
;NWD jest ostatnią dzielną
K06:
Zakończ
PROGRAM
#include <iostream>
using namespace std;
int main()
{
unsigned int a,b,t;
cin >> a >> b;
while(b)
{
t = b;
b = a % b;
a = t;
}
cout << a << endl;
return 0;
}
Program odczytuje z pierwszego
wiersza dwie liczby a i b, a
następnie wypisuje w następnym
wierszu ich NWD.
LICZBY WZGLĘDNIE PIERWSZE
Liczba naturalna m jest względnie pierwsza (ang. coprime) z liczbą
naturalną n wtedy i tylko wtedy, gdy NWD(m,n) = 1. Definicja ta oznacza, iż
liczby n i m nie posiadają wspólnych podzielników za wyjątkiem 1.
Problem:
W przedziale <a,b> liczb naturalnych wyszukać wszystkie liczby względnie
pierwsze (ang. relatively prime integers) z zadaną liczbą p.
Rozwiązanie:
Przechodzimy przez kolejne liczby w przedziale <a,b>. Dla każdej liczby
obliczamy algorytmem Euklidesa jej NWD z liczbą p. Jeśli wynikiem będzie 1,
to obie liczby są względnie pierwsze, zatem wyprowadzamy liczbę z
przedziału na wyjście.
Algorytm wyznaczania liczb względnie pierwszych
Wejście
a – początek przedziału, a ∈ N
b – koniec przedziału, b ∈ N
p – liczba służąca do wyznaczenia w przedziale <a,b> liczb z nią względnie pierwszych, p ∈ N
Wyjście:
liczby z przedziału <a,b>, które są względnie pierwsze z liczbą p
Zmienne pomocnicze:
i – przebiega przez kolejne liczby w przedziale <a,b>. i ∈ N
t – tymczasowo przechowuje dzielnik w algorytmie Euklidesa, t ∈ N
ax – zmienna dla algorytmu Euklidesa. ax ∈ N
bx – zmienna dla algorytmu Euklidesa. bx ∈ N
Lista kroków:
K01:
Dla i = a,a+1,...,b wykonuj kroki K02...K08 ;przechodzimy przez kolejne liczby z
przedziału <a,b>
K02:
ax ← i
;zmienne dla algorytmu Euklidesa
K03:
bx ← p
K04:
Dopóki bx ≠ 0 wykonuj kroki K05...K07
;wyznaczamyNWD(i,p)
K05:
t ← bx
K06:
bx ← ax mod bx
K07:
ax ← t
K08:
Jeśli ax = 1, to pisz i ;NWD(i,p) = 1, zatem i jest względnie pierwsze z p
K09:
Zakończ
PROGRAM
#include <iostream>
using namespace std;
int main()
{
unsigned int a,b,p,ax,bx,i,t;
cin >> a >> b >> p;
for(i = a; i <= b; i++)
{
ax = i; bx = p;
while(bx)
{
t = bx;
bx = ax % bx;
ax = t;
}
if(ax == 1) cout << i << " ";
}
cout << endl;
return 0;
}
Program odczytuje z pierwszego
wiersza trzy liczby a, b i p a
następnie wypisuje wszystkie
liczby w przedziale <a,b>
względnie pierwsze z p.
LICZBY PIERWSZE – GENERACJA PRZEZ
SPRAWDZANIE PODZIELNOŚCI
Problem:
Znaleźć n kolejnych liczb pierwszych
Liczba naturalna p jest liczbą pierwszą - posiadającą
dokładnie dwa różne podzielniki: 1 i siebie samą.
Bierzemy kolejne liczby naturalne poczynając od
2. Wybraną liczbę naturalną p próbujemy dzielić przez
liczby od 2 do p-1. Jeśli żadna z tych liczb nie jest
podzielnikiem p, to liczba p jest pierwsza.
ALGORYTM WYZNACZANIA LICZB PIERWSZYCH
PRZEZ SPRAWDZANIE PODZIELNOŚCI
Wejście
n- liczba określająca ile liczb pierwszych należy wygenerować , n ∈ N
Wyjście
n kolejnych liczb pierwszych
Zmienne pomocnicze
lp- zlicza kolejno wygenerowane liczby pierwsze. lp∈N
p- kolejno testowane liczby naturalne. p ∈N
d- kolejne dzielniki. d ∈N
Lista kroków:
K01:lp ← 0
;zerujemy licznik liczb pierwszych
K02: p ←2
;generację rozpoczynamy od 2
K03: Dopóki lp<n, wykonuj kroki K04…K08
;pętla generacji liczb pierwszych
K04: Dla d=2,3…,p-1, wykonuj krok K05
;pętla sprawdzania podzielności przez p i d
K05: Jeśli p mod d=0,idś do K08
;jeśli p dzieli się przez d, to nie jest pierwsza
K06: Pisz p
;p jest pierwsze
K07: lp ←lp+1
;zwiększamy licznik wygenerowanych liczb pierwszych
K08:p ←p+1
;przechodzimy do kolejnej liczby , kandydata
K09: Zakończ
PROGRAM
#include <iostream>
using namespace std;
int main()
{
unsigned int n,lp,p,d;
bool t;
cin >> n;
lp = 0;
p = 2;
while(lp < n)
{
t = true;
for(d = 2; d < p; d++)
if(p % d == 0)
{
t = false; break;
}
if(t)
{
cout << p << " ";
lp++;
}
p++;
}
cout << endl;
return 0;
}
Program w pierwszym wierszu czyta
liczbę n i w następnych wierszach
wypisuje n kolejnych liczb pierwszych.
LICZBY PIERWSZE – SITO ERATOSTENESA
Sito Eratostenesa jest algorytmem
dwuprzebiegowym. Najpierw dokonuje on eliminacji
liczb złożonych ze zbioru zaznaczając je w określony
sposób, a w drugim obiegu przegląda zbiór ponownie
wyprowadzając na wyjście liczby, które nie zostały
zaznaczone. Na tym polu można dokonywać różnych
optymalizacji. W pierwszym podejściu zastosujemy
tablicę wartości logicznych S. Element S[i] będzie
odpowiadał liczbie o wartości i. Zawartość S[i] będzie
z kolei informowała o tym, czy liczba i pozostała w
zbiorze (S[i] = true) lub została usunięta (S[i] = false).
Rozwiązanie :
Najpierw przygotowujemy tablicę reprezentującą zbiór liczbowy wypełniając
ją wartościami logicznymi true. Odpowiada to umieszczeniu w zbiorze
wszystkich liczb wchodzących w zakres od 2 do n. Następnie z tablicy
będziemy usuwali kolejne wielokrotności początkowych liczb od 2 do
pierwiastka całkowitego z n w pisując do odpowiednich elementów wartość
logiczną false. Na koniec przeglądniemy zbiór i wypiszemy indeksy
elementów zawierających wartość logiczną true – odpowiadają one liczbom,
które w zbiorze pozostały.
Za pierwszą wielokrotność do wyrzucenia ze zbioru przyjmiemy kwadrat
liczby i. Przyjrzyj się naszemu przykładowi. Gdy wyrzucamy wielokrotności
liczby 2, to pierwszą z nich jest 4 = 22. Następnie dla wielokrotności liczby 3
pierwszą do wyrzucenia jest 9 = 32, gdyż 6 zostało wyrzucone wcześniej jako
wielokrotność 2. Dla 5 będzie to 25 = 52, gdyż 10 i 20 to wielokrotności 2, a 15
jest wielokrotnością 3, itd. Pozwoli to wyeliminować zbędne obiegi pętli
usuwającej wielokrotności.
ALGORYTM SITA ERATOSTENESA
Wejście
n – liczba określająca górny kraniec przedziału poszukiwania liczb pierwszych, n N, n > 1
Wyjście:
Kolejne liczby pierwsze w przedziale od 2 do n.
Zmienne pomocnicze
S – tablica wartości logicznych. S[i] {false,true}, dla i = 2,3,...,n.
g –zawiera granicę wyznaczania wielokrotności. g N
i –przebiega przez kolejne indeksy elementów S[i]. i N
w –wielokrotności wyrzucane ze zbioru S, w N
Lista kroków:
K01: Dla i = 2,3,...,n wykonuj S[i] ← true
; zbiór początkowo zawiera wszystkie liczby
K02:g ← [√n]
; obliczamy granicę eliminowania wielokrotności
K03:Dla i = 2,3,...,g wykonuj kroki K04...K08 ; w pętli wyrzucamy ze zbioru wielokrotności i
K04:Jeśli S[i] = false, to następny obieg pętli K03
; sprawdzamy, czy liczba i jest w zbiorze
K05: w ← i2
; jeśli tak, wyrzucamy jej wielokrotności
K06: Dopóki w ≤ n wykonuj kroki K07...K08 ; ze zbioru
K07: S[w] ← false
K08:w ← w + i
; następna wielokrotność
K09:Dla i = 2,3,...,n wykonuj krok K10
; przeglądamy zbiór wynikowy
K10:Jeśli S[i] = true, to pisz i
; wyprowadzając pozostałe w nim liczby
K11:Zakończ
PROGRAM
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
unsigned int g,i,n,w;
bool * S;
cin >> n;
S = new bool[n + 1];
for(i = 2; i <= n; i++) S[i] = true;
g = (unsigned int)sqrt(n);
for(i = 2; i <= g; i++)
if(S[i])
{
w = i * i;
while(w <= n)
{
S[w] = false; w += i; }
}
for(i = 2; i <= n; i++) if(S[i]) cout << i << " ";
cout << endl;
delete [] S;
return 0;
}
Program w pierwszym wierszu czyta
liczbę n i w następnych wierszach
wypisuje kolejne liczby pierwsze
zawarte w przedziale od 2 do n.
NAJMNIEJSZA WSPÓLNA WIELOKROTNOŚĆ
Problem:
Dla danych liczb naturalnych a i b znaleźć najmniejszą
liczbę naturalną c, która jest podzielna bez reszty przez a i
przez b.
Liczba naturalna c o takich własnościach nosi nazwę
NWW – najmniejszej wspólnej wielokrotności liczb a i b
(ang. the least common multiple of a and b). Sposób
obliczania NWW jest bardzo prosty:
NWW(a,b) = a × b
NWD(a,b)
Jeśli liczby a i b są względnie pierwsze, to NWD(a,b) = 1.
Wtedy NWW(a,b) = a × b.
ALGORYTM WYZNACZANIA NAJMNIEJSZEJ
WSPÓLNEJ WIELOKROTNOŚCI
Wejście
a,b– liczby, których NWW poszukujemy, a,b N
Wyjście:
NWW – najmniejsza wspólna wielokrotność liczb a i b.
Zmienne pomocnicze
ab – zapamiętuje iloczyn a i b. ab N
t – tymczasowo przechowuje dzielnik w algorytmie Euklidesa, t N
Lista kroków:
K01:
ab ← a × b
; zapamiętujemy iloczyn a i b
K02:
Dopóki b ≠ 0 wykonuj kroki K03...K05
; algorytmem Euklidesa
znajdujemy NWD(a,b)
K03:
t←b
K04:
b ← a mod b
K05:
a←t
K06:
ab ← ab div a
; obliczamy NWW
K07:
Pisz ab
K08:
Zakończ
PROGRAM
#include <iostream>
using namespace std;
int main()
{
unsigned long long a,b,t,ab;
cin >> a >> b;
ab = a * b;
while(b)
{
t = b;
b = a % b;
a = t;
}
ab /= a;
cout << ab << endl << endl;
return 0;
}
Program odczytuje z pierwszego
wiersza liczby a i b. W następnym
wierszu wypisuje NWW(a,b).
Download