PROBLEM. Znaleźć rozkład liczby p > 1. na iloczyn czynników pierwszych.

Podobne dokumenty
Liczby całkowite i rzeczywiste

Problem W przedziale całkowitym <a,b> wyszukaj wszystkie liczby parzyste.

Algorytmy i struktury danych. Wykład 4

Luty 2001 Algorytmy (7) 2000/2001

Iteracje. Algorytm z iteracją to taki, w którym trzeba wielokrotnie powtarzać instrukcję, aby warunek został spełniony.

WYKŁAD 3 (13 MARZEC 2014) LICZBY CAŁKOWITE I RZECZYWISTE. Bartosz Łakomy i Dariusz Dobiesz

B.B. 2. Sumowanie rozpoczynamy od ostatniej kolumny. Sumujemy cyfry w kolumnie zgodnie z podaną tabelką zapisując wynik pod kreską:

do instrukcja while (wyrażenie);

Dr inż. Robert Wójcik, p. 313, C-3, tel Katedra Informatyki Technicznej (K-9) Wydział Elektroniki (W-4) Politechnika Wrocławska

ALGORYTMY Algorytm poprawny jednoznaczny szczegółowy uniwersalny skończoność efektywność (sprawność) zmiennych liniowy warunkowy iteracyjny

1. Napisz program, który wyświetli Twoje dane jako napis Witaj, Imię Nazwisko. 2. Napisz program, który wyświetli wizytówkę postaci:

Zadania do samodzielnego rozwiązania

LISTA 5. C++ PETLE for, while, do while

Algorytmy w teorii liczb

Zaawansowane algorytmy i struktury danych

ARYTMETYKA BINARNA. Dziesiątkowy system pozycyjny nie jest jedynym sposobem kodowania liczb z jakim mamy na co dzień do czynienia.

Plan wynikowy z wymaganiami edukacyjnymi z matematyki w zakresie podstawowym dla klasy 1 zsz Katarzyna Szczygieł

1. Operacje logiczne A B A OR B

Przykładowe zadania z teorii liczb

WHILE (wyrażenie) instrukcja;

Zadanie 1. Zmiana systemów. Zadanie 2. Szyfr Cezara. Zadanie 3. Czy liczba jest doskonała. Zadanie 4. Rozkład liczby na czynniki pierwsze Zadanie 5.

WHILE (wyrażenie) instrukcja;

1. LICZBY DZIAŁ Z PODRĘCZNIKA L.P. NaCoBeZu kryteria sukcesu w języku ucznia

WYMAGANIA NA POSZCZEGÓLNE OCENY MATEMATYKA KL.VII

wagi cyfry pozycje

Liczby. Wymagania programowe kl. VII. Dział

Pętla for. Matematyka dla ciekawych świata -19- Scilab. for i=1:10... end. for k=4:-1:1... end. k=3 k=4. k=1. k=2

Wymagania edukacyjne z matematyki w klasie VII szkoły podstawowej

Matematyka z kluczem. Szkoła podstawowa nr 18 w Sosnowcu. Przedmiotowe zasady oceniania klasa 7

WYMAGANIA EDUKACYJNE Z MATEMATYKI KLASA VII

4. Postęp arytmetyczny i geometryczny. Wartość bezwzględna, potęgowanie i pierwiastkowanie liczb rzeczywistych.

Algorytm i złożoność obliczeniowa algorytmu

Arytmetyka komputera. Na podstawie podręcznika Urządzenia techniki komputerowej Tomasza Marciniuka. Opracował: Kamil Kowalski klasa III TI

Obliczenia iteracyjne

2 Arytmetyka. d r 2 r + d r 1 2 r 1...d d 0 2 0,

ALGORYTMY. 1. Podstawowe definicje Schemat blokowy

Zadanie 1. Algorytmika ćwiczenia

Zadanie 1. Potęgi (14 pkt)

Rekurencja (rekursja)

Schematy blokowe I. 1. Dostępne bloki: 2. Prosty program drukujący tekst.

Programowanie w Baltie klasa VII

Metody numeryczne. dr Artur Woike. Ćwiczenia nr 2. Rozwiązywanie równań nieliniowych metody połowienia, regula falsi i siecznych.

Katarzyna Bereźnicka Zastosowanie arkusza kalkulacyjnego w zadaniach matematycznych. Opiekun stypendystki: mgr Jerzy Mil

Wstęp do Informatyki

Języki programowania zasady ich tworzenia

Wymagania edukacyjne z matematyki dla klasy 7 na podstawie planu wynikowego z rozkładem materiału

5. Rozwiązywanie układów równań liniowych

Funkcje wymierne. Jerzy Rutkowski. Działania dodawania i mnożenia funkcji wymiernych określa się wzorami: g h + k l g h k.

Programowanie dynamiczne

ZADANIE 1. Ważenie (14 pkt)

Systemy liczbowe. 1. Przedstawić w postaci sumy wag poszczególnych cyfr liczbę rzeczywistą R = (10).

Zadania do wykonania. Rozwiązując poniższe zadania użyj pętlę for.

Matematyka dyskretna

ALGORYTMY. 1. Podstawowe definicje Schemat blokowy

1. Informatyka - dyscyplina naukowa i techniczna zajmująca się przetwarzaniem informacji.

Matematyka z kluczem. Plan wynikowy z rozkładem materiału Klasa 7

Matematyka z kluczem. Plan wynikowy z rozkładem materiału Klasa 7

Rekurencja. Przykład. Rozważmy ciąg

LICZBY PIERWSZE. Jan Ciurej Radosław Żak

Wymagania edukacyjne z matematyki na poszczególne do klasy VII szkoły podstawowej na rok szkolny 2018/2019

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

Wykład 4. Określimy teraz pewną ważną klasę pierścieni.

Metody numeryczne I Równania nieliniowe

1. Liczby naturalne, podzielność, silnie, reszty z dzielenia

Złożoność obliczeniowa zadania, zestaw 2

Funkcja kwadratowa. f(x) = ax 2 + bx + c = a

WYMAGANIA EDUKACYJNE Z MATEMATYKI dla klasy I ba Rok szk. 2012/2013

Sortowanie przez wstawianie Insertion Sort

Arytmetyka. Arytmetyka. Magdalena Lemańska. Magdalena Lemańska,

I. Podstawy języka C powtórka

Samodzielnie wykonaj następujące operacje: 13 / 2 = 30 / 5 = 73 / 15 = 15 / 23 = 13 % 2 = 30 % 5 = 73 % 15 = 15 % 23 =

Algorytm. a programowanie -

PRÓBNY EGZAMIN MATURALNY Z INFORMATYKI STYCZEŃ POZIOM ROZSZERZONY Część I

Liczby rzeczywiste. Działania w zbiorze liczb rzeczywistych. Robert Malenkowski 1

Operacje arytmetyczne

Podstawy programowania. Wykład: 13. Rekurencja. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

CIĄGI wiadomości podstawowe

Sortowanie Shella Shell Sort

Projekt Era inżyniera pewna lokata na przyszłość jest współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego

Wymagania edukacyjne niezbędne do uzyskania rocznych ocen klasyfikacyjnych z matematyki w klasie VII.

Pzetestuj działanie pętli while i do...while na poniższym przykładzie:

Konstrukcje warunkowe Pętle

Jarosław Wróblewski Matematyka Elementarna, zima 2015/16

Transponowanie macierzy Mnożenie macierzy Potęgowanie macierzy Wyznacznik macierzy

1 Metody rozwiązywania równań nieliniowych. Postawienie problemu

Wybrane zagadnienia teorii liczb

Instrukcje pętli przykłady. Odgadywanie hasła. 1) Program pyta o hasło i podaje adres, gdy hasło poprawne lub komunikat o błędnym haśle.

Akademia Górniczo-Hutnicza im. Stanisława Staszica w Krakowie Olimpiada O Diamentowy Indeks AGH 2017/18. Informatyka Etap III

Systemy zapisu liczb.

WYMAGANIA EDUKACYJNE Z MATEMATYKI DLA KLASY VII SZKOŁY PODSTAWOWEJ

TEORETYCZNE PODSTAWY INFORMATYKI

Kodowanie i kompresja Streszczenie Studia Licencjackie Wykład 15, Kryptografia: algorytmy asymetryczne (RSA)

Wymagania dla klasy siódmej. Treści na 2 na 3 na 4 na 5 na 6 Uczeń: Uczeń: Uczeń: Uczeń: Uczeń: DZIAŁ 1. LICZBY

Przedmiotowy system oceniania wraz z określeniem wymagań edukacyjnych klasa druga zakres rozszerzony

Kod znak-moduł. Wartość liczby wynosi. Reprezentacja liczb w kodzie ZM w 8-bitowym formacie:

Funkcja kwadratowa. f(x) = ax 2 + bx + c,

2) R stosuje w obliczeniach wzór na logarytm potęgi oraz wzór na zamianę podstawy logarytmu.

Czas pracy: 60 minut

Transkrypt:

PROBLEM Znaleźć rozkład liczby p > 1. na iloczyn czynników pierwszych. Postawiony problem posiada bardzo duże znaczenie w wielu dziedzinach informatyki szczególnie w kryptografii. Na dzień dzisiejszy nie istnieje powszechnie znany żaden szybki algorytm rozkładu dużej liczby naturalnej na czynniki pierwsze. Na tym fakcie opierają swoje bezpieczeństwo współczesne systemy szyfrowania informacji np. RSA. Dla przykładu rozkład 200 cyfrowej liczby zajął 18 miesięcy wielu komputerom pracującym w sieci w sumie czas obliczeń dla pojedynczej maszyny wyniósł ponad pół wieku! Zasadnicze twierdzenie arytmetyki mówi, iż każda liczba naturalna większa od 1 może być jednoznacznie zapisana jako iloczyn liczb pierwszych

Na przykład: 1200 = 2 4 3 5 2 i nie istnieje żaden inny rozkład dla liczby 1200 Znając rozkład liczby na czynniki pierwsze można dla niej określić wszystkie możliwe podzielniki. Na przykład każdy podzielnik liczby 1200 da się zapisać jako: p 1200 = 2 a 3 b 5 c, gdzie a {0,1,2,3,4}, b {0,1}, c {0,1,2} Zatem wszystkich możliwych podzielników jest tyle ile wynosi iloczyn liczebności możliwych wartości a, b i c: 5 x 2 x 3 = 30 Podstawowe twierdzenie arytmetyki mówi nam, iż rozkład na czynniki pierwsze jest zawsze możliwy i jednoznaczny, lecz nie mówi, jak tego mamy dokonać.

Rozwiązanie 1 Pierwsze podejście do znalezienia rozkładu liczby p na jej czynniki pierwsze jest bardzo prymitywne, chociaż daje oczywiście poprawny wynik. Nazywa się ono bezpośrednim poszukiwaniem rozkładu na czynniki pierwsze. Będziemy sprawdzać podzielność liczby p przez kolejne liczby naturalne od 2 do pierwiastka z p. Jeśli liczba p będzie podzielna przez daną liczbę, to liczbę wyprowadzimy na wyjście, a za nowe p przyjmiemy wynik dzielenia i próbę dzielenia będziemy powtarzać dotąd, aż nie będzie to już możliwe. Wtedy przejdziemy do następnego dzielnika.

Przykład: Rozłożyć liczbę 44100 na czynniki pierwsze. Podział Reszta Czynnik Znalezione czynniki Uwagi 44100 : 2 = 22050 0 2 2 dzieli się 22050 : 2 = 11025 0 2 2 2 dzieli się 11025 : 2 = 5512 1 X 2 2 nie dzieli się 11025 : 3 = 3675 0 3 2 2 3 dzieli się 3675 : 3 = 1225 0 3 2 2 3 3 dzieli się 1225 : 3 = 408 1 X 2 2 3 3 nie dzieli się 1225 : 4 = 306 1 X 2 2 3 3 nie dzieli się 1225 : 5 = 245 0 5 2 2 3 3 5 dzieli się 245 : 5 = 49 0 5 2 2 3 3 5 5 dzieli się 49 : 5 = 9 4 X 2 2 3 3 5 5 nie dzieli się 49 : 6 = 8 1 X 2 2 3 3 5 5 nie dzieli się 49 : 7 = 7 0 7 2 2 3 3 5 5 7 dzieli się 7 : 7 = 1 0 7 2 2 3 3 5 5 7 7 dzieli się 44100 = 2 2 3 3 5 5 7 7 Kończymy, ponieważ wynik ostatniego dzielenia jest równy 1

ALGORYTM ROZKŁADU LICZBY NATURALNEJ NA CZYNNIKI PIERWSZE Wejście p liczba rozkładana na czynniki pierwsze, p ϵ N, p > 1 Wyjście: Czynniki pierwsze liczby p. Elementy pomocnicze: g granica sprawdzania podzielności liczby p. g ϵ N i kolejne podzielniki, i ϵ N

Lista kroków: K01: g [ p] ; granica sprawdzania czynników pierwszych K02: Dla i = 2,3,...,g wykonuj kroki K03...K06 ; w pętli sprawdzamy podzielność liczby p przez kolejne liczby K03: Dopóki p mod i = 0 ; dopóki dzielnik dzieli p K04: Pisz i ; wyprowadzamy go i K05: p p div i ; dzielimy przez niego p K06: Jeśli p = 1, to zakończ ; pętlę przerywamy, gdy stwierdzimy brak dalszych dzielników K07: Jeśli p > 1, to pisz p ; p może posiadać ostatni czynnik większy od pierwiastka z p K08: Zakończ

Program w pierwszym wierszu czyta liczbę p i w następnym wierszu wypisuje kolejne czynniki pierwsze tej liczby.

ROZWIĄZANIE 2 Poprzedni algorytm sprawdza podzielność liczby p przez wszystkie kolejne liczby naturalne, zawarte w przedziale <2, p>. Tymczasem poszukiwane podzielniki muszą być liczbami pierwszymi. Jeśli nie mamy liczb pierwszych pod ręką, to przynajmniej możemy ograniczyć dzielenia do liczb 2, 3 oraz 6k±1, dla k = 1,2... wpadających w przedział <2, p>. Prezentowany poniżej algorytm dokonuje takiej właśnie optymalizacji, redukując do 1 / 3 liczbę sprawdzanych podzielników

ALGORYTM ROZKŁADU LICZBY NATURALNEJ NA CZYNNIKI PIERWSZE Wejście p liczba rozkładana na czynniki pierwsze, p ϵ N, p > 1 Wyjście: Czynniki pierwsze liczby p. Elementy pomocnicze: g granica sprawdzania podzielności liczby p. g ϵ N i kolejne podzielniki, i ϵ N k,d zmienne do generacji liczb postaci 6k±1, k N, d {-1, 1}

LISTA KROKÓW K01:g [ p]; wyznaczamy granicę sprawdzania podzielności K02:k 1; d -1; współczynniki do generacji liczb postaci 6k±1 K03:i 2; początek sprawdzania podzielności K04:Dopóki i g wykonuj kroki K05...K12 K05: Dopóki p mod i = 0 wykonuj kroki K06...K07; wyznaczamy dzielnik p K06: Pisz i K07: p p div i; modyfikujemy p K08: Jeśli p = 1, to idź do K14; p nie jest już podzielne K09: Jeśli i 3, to idź do K11; wyznaczamy następny podzielnik K10: i i + 1 i następny obieg pętli K04; podzielniki 2 i 3 K11: i 6k + d; pozostałe, postaci 6k±1 K12: Jeśli d = 1, to d -1; k k + 1 inaczej d 1; modyfikujemy współczynniki dla następnego podzielnika K13:Jeśli p 1, to pisz p; ewentualny, ostatni podzielnik K14:Zakończ Mamy program, który wczytuje liczbę p i wypisuje jej czynniki pierwsze:

Program w pierwszym wierszu czyta liczbę p i w następnym wierszu wypisuje kolejne czynniki pierwsze tej liczby

PROBLEM: SPRAWDZIĆ, CZY LICZBA NATURALNA Rozwiązanie 1 P JEST PIERWSZA. Liczba jest pierwsza,jeśli nie posiada dzielników ( innych poza 1 i sobą samą. Pierwsze rozwiązanie testu na pierwszość polega na próbnym dzieleniu liczby p przez liczby z przedziału od 2 do [ p] i badaniu reszty z dzielenia. Powód takiego postępowania jest prosty jeśli liczba p posiada czynnik większy od pierwiastka z p, to drugi czynnik musi być mniejszy od pierwiastka, aby ich iloczyn był równy p. W przeciwnym razie iloczyn dwóch liczb większych od p dawałby liczbę większą od p. Zatem wystarczy przebadać podzielność p przez liczby z przedziału <2,[ p]>, aby wykluczyć liczby złożone.

ALGORYTM SPRAWDZANIA PIERWSZOŚCI LICZBY NATURALNEJ Wejście p liczba badana na pierwszość, p N, p > 1 Wyjście: TAK, jeśli p jest pierwsze lub NIE w przypadku przeciwnym. Elementy pomocnicze: g granica sprawdzania podzielności p. g Ni kolejne podzielniki liczby p, i N Lista kroków: K01:g [ p] ; wyznaczamy granicę sprawdzania podzielności p K02:Dla i = 2,3,...,g wykonuj krok K03 ; przebiegamy przez przedział <2,[ p]> K03: Jeśli p mod i = 0, to pisz NIE i zakończ ; jeśli liczba z przedziału <2,[ p]> dzieli p, to p nie jest pierwsze K04:Pisz TAK ; jeśli żadna liczba z <2,[ p]> nie dzieli p, p jest pierwsze K05:Zakończ

Program odczytuje w pierwszym wierszu liczbę p, a w drugim wierszu wypisuje słowo TAK, jeśli liczba p jest pierwsza lub NIE w przypadku przeciwnym. W programie zastosowano zmienne 64 bitowe, zatem zakres p jest dosyć duży. Jednakże dla wielkich liczb naturalnych test na pierwszość może zająć wiele czasu.

ROZWIĄZANIE 2 Liczba p jest liczbą pierwszą, jeśli nie dzieli się przez żadną liczbę pierwszą z przedziału <2,[ p]>. Wszystkie liczby pierwsze z wyjątkiem 2 są liczbami nieparzystymi. Możemy zatem w poprzednim algorytmie zmniejszyć dwukrotnie liczbę potrzebnych dzieleń, jeśli liczbę p będziemy dzielić przez kolejne liczby nieparzyste z przedziału <2,[ p]>. Oczywiście najpierw należy wykonać test podzielności przez 2.

ALGORYTM SPRAWDZANIA PIERWSZOŚCI LICZBY NATURALNEJ Wejście p liczba badana na pierwszość, p N, p > 1Wyjście: TAK, jeśli p jest pierwsze lub NIE w przypadku przeciwnym. Elementy pomocnicze: g granica sprawdzania podzielności p. g Ni kolejne podzielniki liczby p, i N Lista kroków: K01Jeśli p = 2, to idź do K08; liczba 2 jest pierwsza K02:Jeśli p mod 2 = 0, to idź do K10; sprawdzamy podzielność przez 2 K03:g [ p]; granica sprawdzania podzielności K04:i 3; pierwszy podzielnik nieparzysty K05:Dopóki i g, wykonuj kroki K06...K07; w pętli sprawdzamy podzielność przez podzielniki nieparzyste K06: Jeśli p mod i = 0, to idź do K10 K07: i i + 2; następny podzielnik nieparzysty K08:Pisz "TAK"; p nie dzieli się, zatem jest pierwsze K09:Zakończ K10:Pisz "NIE"; p jest podzielne, zatem nie jest pierwsze K11:Zakończ

Program odczytuje w pierwszym wierszu liczbę p, a w drugim wierszu wypisuje słowo TAK, jeśli liczba p jest pierwsza lub NIE w przypadku przeciwnym

ROZWIĄZANIE 3 Liczbę niezbędnych dzieleń można dalej ograniczyć, jeśli liczbę p będziemy dzielić przez dzielniki: 2, 3 oraz 6k ± 1, dla k = 1,2,..., 6k ± 1 <2,[ p]>. Dwa pierwsze dzielniki są początkowymi liczbami pierwszymi. Gdy wyeliminujemy czynniki 2 i 3, pozostałe liczby pierwsze muszą przybrać postać 6k ± 1. Wyjaśnienie jest bardzo proste: 6k = 2 3 k liczby podzielne przez 2 i 3 nie są pierwsze 6k ± 2 = 2 (3k ± 1) liczby podzielne przez 2 nie są pierwsze 6k ± 3 = 3 (2k ± 1) liczby podzielne przez 3 nie są pierwsze 6k ± 4 = 2 (3k ± 2) liczby podzielne przez 2 nie są pierwsze Pozostają liczby postaci: 6k ± 1, które mogą być pierwsze (ale nie muszą!). Jednakże liczb tych jest 1 / 3 w stosunku do pierwotnego algorytmu, co zaowocuje zmniejszeniem liczby wykonywanych dzieleń

ALGORYTM SPRAWDZANIA PIERWSZOŚCI LICZBY NATURALNEJ Wejście p liczba badana na pierwszość, p N, p > 1Wyjście: TAK, jeśli p jest pierwsze lub NIE w przypadku przeciwnym. Elementy pomocnicze: g granica sprawdzania podzielności p. g ϵ N i podzielniki liczby p, i ϵ N k mnożnik do wyznaczania podzielników postaci 6k ± 1, k ϵ N d zmienna pomocnicza do wyznaczania podzielników, d ϵ {false,true}

LISTA KROKÓW: K01: g [ p]; wyznaczamy granicę sprawdzania podzielności K02: i 2; pierwszy dzielnik K03: k 1; d false;; ustawiamy zmienne pomocnicze K04: Dopóki i g, wykonuj kroki K05...K14 K05: Jeśli p mod i = 0, to idź do K17; sprawdzamy podzielność p przez i K06: Jeśli i > 2, to idź do K09; podzielniki > 3 generujemy wg wzoru 6k ± 1 K07: i i + 1; podzielniki 2 i 3 K08: Następny obieg pętli K04 K09: d d; generujemy podzielnik i = 6k ± 1 K10: i 6k K11: Jeśli d = true, to idź do K14 K12: k k + 1 K13 i i + 1 i następny obieg pętli K04 K14 i i - 1 K15:Pisz "TAK"; p nie dzieli się przez żaden z dzielników K16:Zakończ K17:Pisz "NIE"; p nie jest pierwsze K18:Zakończ

Program odczytuje w pierwszym wierszu liczbę p, a w drugim wierszu wypisuje słowo TAK, jeśli liczba p jest pierwsza lub NIE w przypadku przeciwnym.

PROBLEM : DANY, SKOŃCZONY ZBIÓR LICZB CAŁKOWITYCH POMIESZAĆ PSEUDOLOSOWO Mieszanie pseudolosowe Zadanie mieszania, tasowania zawartości tablicy sprowadza się do wykonywania w pętli zamiany miejscami dwóch elementów tablicy o wylosowanych indeksach. Pętla musi być wykonana tyle razy, aby tasowanie objęło wszystkie elementy w praktyce wystarcza ilość wykonań równa 3n, gdzie n jest ilością elementów.

ALGORYTM MIESZANIA PSEUDOLOSOWEGO Wejście n liczba elementów w tablicy, n ϵ N Z tablica elementów, indeksy rozpoczynają się od 0 Wyjście: Tablica Z z potasowaną zawartością Zmienne pomocnicze i licznik obiegów pętli, iϵ N x przechowuje element tablicy Z przy zamianie zawartości. Typ ten sam, co elementy tablicy Z.losowa(x) funkcja zwracająca liczbę pseudolosową z zakresu od 0 do x - 1 Lista kroków: K01:Dla i = 1,2,...,3n: wykonuj K02...K07; tasowanie wykonujemy w pętli K02: i 1 losowa(n); losujemy pierwszy indeks K03: i 2 losowa(n); losujemy drugi indeks K04: x Z[i 1 ]; zamieniamy miejscami Z[i 1 ] i Z[i 2 ] K05: Z[i 1 ] Z[i 2 ] K06: Z[i 2 ] x K07:Zakończ

Program tasuje tablicę 10 elementów całkowitych o kolejnych wartościach od 0 do 9. Tablica jest najpierw wyświetlana przed tasowaniem, a następnie po tasowaniu.

PROBLEM : WYLOSOWAĆ Z PRZEDZIAŁU CAŁKOWITEGO <A,B> N LICZB PSEUDOLOSOWYCH BEZ POWTÓRZEŃ. Losowanie bez powtórzeń Zadanie losowania bez powtórzeń można rozwiązać na kilka różnych sposobów. Jeśli przedział <a,b> jest mały (np. zawiera 80 kolejnych liczb Multi-Lotka), to możemy go odwzorować w tablicy, następnie zawartość tej tablicy potasować poprzednio podanym algorytmem i jako wynik zwrócić pierwsze n elementów. Tasowanie nie dubluje elementów tablicy, zatem otrzymamy n liczb bez powtórzeń. Taki algorytm posiada klasę złożoności obliczeniowej O(n). Jeśli przedział <a,b> jest bardzo duży, a n stosunkowo małe, to postępujemy w sposób następujący. Przygotowujemy pustą tablicę o n elementach. Losujemy liczbę pseudolosową. Jeśli wylosowana liczba jest już w tablicy, to losujemy ponownie dotąd, aż wylosowanej liczby nie będzie w tablicy. Liczbę dopisujemy do tablicy. Jeśli tablica jest zapełniona, kończymy. W przeciwnym razie powtarzamy losowanie. Algorytm w takiej postaci posiada optymistyczną klasę złożoności obliczeniowej O(n 2 ).

ALGORYTM LOSOWANIA BEZ POWTÓRZEŃ Wejście n liczba określająca, ile liczb pseudolosowych bez powtórzeń należy wylosować, n ϵ N a,b liczby określające całkowity przedział losowania, b - a n, a,b ϵc Wyjście: n różnych od siebie liczb pseudolosowych z przedziału <a,b> Zmienne pomocnicze T tablica przechowująca wylosowane liczby pseudolosowe. Indeksy od 0 do n-1. i licznik wylosowanych liczb pseudolosowych, i ϵ N j wykorzystywane do przeszukiwania tablicy T, j ϵ N x wylosowana liczba pseudolosowalosowa (x) funkcja zwracająca liczbę pseudolosową z zakresu od 0 do x - 1 Lista kroków: K01:Dla i = 0,1,...,n-1 wykonuj K02...K06 K02: x a + losowa(b - a + 1); losujemy liczbę pseudolosową K03: Dla j = 0,1,...,i - 1 wykonuj K04; sprawdzamy, czy wylosowana liczba jest w T K04: Jeśli T[j] = x, to idź do K02; jeśli tak, powtarzamy losowanie K05: T[i] x; jeśli nie, zapamiętujemy w T wylosowaną liczbę K06: Wyprowadź x; wyprowadzamy liczbę na wyjście K07:Zakończ

W pierwszym wierszu program odczytuje trzy liczby: a,b krańce przedziału, n ilość liczb pseudolosowych do wylosowania. Jeśli długość przedziału <a,b> pozwala na wygenerowanie zadanej ilości różnych liczb pseudolosowych, to program je generuje i wyświetla w następnym wierszu. W przeciwnym razie wypisuje odpowiedni komunikat.

PROBLEM: WYZNACZYĆ N-TY WYRAZ CIĄGU FIBONACCIEGO. Leonardo Fibonacci był włoskim matematykiem żyjącym w latach od 1175 do 1250. Jest on autorem specyficznego ciągu liczbowego, który pojawia się w wielu zastosowaniach informatycznych (i nie tylko). Wyrazy ciągu Fibonacciego definiujemy rekurencyjnie w sposób następujący: F 0 = 0 F 1 = 1 F i = F i-2 + F i-1, dla i > 1 Oto kilka pierwszych wyrazów ciągu Fibonacciego: 0 1 1 2 3 5 8 13 21 34 55 89..

ROZWIĄZANIE PIERWSZE ROZWIĄZANIE OPIERAMY BEZPOŚREDNIO NA DEFINICJI WYKORZYSTUJĄC WYWOŁANIA REKURENCYJNE. JEST TO BARDZO ZŁE ROZWIĄZANIE (PODAJEMY JE TYLKO ZE WZGLĘDÓW DYDAKTYCZNYCH), PONIEWAŻ ALGORYTM WIELOKROTNIE OBLICZA WYRAZY CIĄGU, CO W EFEKCIE PROWADZI DO WYKŁADNICZEJ KLASY ZŁOŻONOŚCI OBLICZENIOWEJ O(2 N ). DLA DUŻYCH N CZAS OBLICZEŃ MOŻE SIĘGAĆ MILIARDÓW... MILIARDÓW TYSIĄCLECI. Algorytm generacji liczb Fibonacciego metodą rekurencyjną: Wejście n numer liczby ciągu Fibonacciego do wyliczenia, n ϵn Wyjście: n-ta liczba ciągu Fibonacciego Lista kroków funkcji Fibo(n) K01:Jeśli n 1, to zwróć n i zakończ; f 0 lub f 1 K02:Zwróć Fibo(n - 2) + Fibo(n - 1) i zakończ; dwa wywołania rekurencyjne

W pierwszym wierszu program odczytuje n numer liczby Fibonacciego do wyliczenia. W następnym wierszu program wypisuje wartość n-tej liczby Fibonacciego. Z uwagi na wykładniczą klasę złożoności obliczeniowej czas obliczeń szybko rośnie, zatem nie podawaj zbyt dużych n (<45), inaczej nie doczekasz się wyniku lub komputer zgłosi przepełnienie pamięci.

ROZWIĄZANIE DRUGIE Poprzednie rozwiązanie jest bardzo proste. Niestety wywołania rekurencyjne powodują, iż komputer wielokrotnie oblicza te same liczby Fibonacciego. W ramach ćwiczeń proponuję dodać w wywołaniu funkcji Fibo() licznik, który zwiększa swój stan o 1 przy każdym wywołaniu. Na końcu programu, oprócz wartości Fibo(n), wyświetlamy również stan licznika da nam to pojęcie o ilości wywołań rekurencyjnych. Drugie rozwiązanie wykorzystuje zasadę programowania dynamicznego (ang. dynamic programming). Polega ona na tym, iż rozwiązanie wyższego poziomu obliczamy z rozwiązań otrzymanych na poziomie niższym, które odpowiednio zapamiętujemy. Dzięki temu podejściu program nie musi liczyć wszystkich składników od początku, wykorzystuje wyniki poprzednich obliczeń. W efekcie klasa złożoności obliczeniowej algorytmu spadnie do O(n). Jeszcze lepsze rozwiązanie podajemy w rozdziale dotyczącym potęgowania macierzy.

ALGORYTM GENERACJI LICZB FIBONACCIEGO METODĄ ITERACYJNĄ Wejście n numer liczby ciągu Fibonacciego do wyliczenia, n ϵ N Wyjście: n-ta liczba ciągu Fibonacciego Elementy pomocnicze: f 0,f 1,f kolejne trzy liczby Fibonacciego, f 0,f 1,f ϵ C Lista kroków: K01:f 0 0; pierwsza lub f i-2 liczba Fibonacciego K02:f 1 1; druga lub f i-1 liczba Fibonacciego K03:Dla i = 0,1,...,n wykonuj K04...K08 K04: Jeśli i > 1, to idź do K06 K05: f i i następny obieg pętli K03 K06: f f 0 + f 1 ; obliczamy kolejną liczbę Fibonacciego K07 : f 0 f 1 ; zapamiętujemy wyniki obliczeń pośrednich K08: f 1 f; dla następnego obiegu pętli K09:Pisz f K10:Zakończ

Program odczytuje z pierwszego wiersza numer n liczby Fibonacciego, a w następnym wierszu wyświetla jej wartość. Z uwagi na ograniczony zakres liczb 64 bitowych, program wylicza dokładnie maksymalnie 93-cią liczbę ciągu Fibonacciego.

PROBLEM : ZNALEŹĆ KWADRATOWY PIERWIASTEK CAŁKOWITY NIEUJEMNEJ LICZBY RZECZYWISTEJ X. Całkowity pierwiastek kwadratowy (ang. integer square root) jest największą liczbą całkowitą p, która spełnia nierówność: p 2 x

Problem możemy rozwiązać następująco. ROZWIĄZANIE NR 1 Tworzymy ciąg kwadratów kolejnych liczb całkowitych począwszy od 0: 0 2 1 2 2 2 3 2...i 2 do momentu, gdy dla pewnego i otrzymamy spełnioną nierówność i 2 > x. Wtedy p = i - 1. Pozostaje do rozwiązania efektywny sposób tworzenia kwadratów kolejnych liczb całkowitych. Wypiszmy kilkanaście początkowych wyrazów tego ciągu:... i 0 1 2 3 4 5 6 7 8 9 10 11 12 i 2 0 1 4 9 16 25 36 49 64 81 100 121 144

Teraz policzmy ciąg różnic pierwszego rzędu: r 1i = i 2 - (i-1) 2, dla i > 0. Różnica pierwszego rzędu powstaje przez odjęcie od wyrazu i-tego jego poprzednika w ciągu, czyli wyrazu (i - 1)-szego. i 0 1 2 3 4 5 6 7 8 9 10 11 12... i 2 0 1 4 9 16 25 36 49 64 81 100 121 144... r 1 1 3 5 7 9 11 13 15 17 19 21 23...

Ciekawa rzecz różnice pierwszego rzędu dla naszego ciągu tworzą ciąg kolejnych liczb nieparzystych. Teraz analogicznie utwórzmy ciąg różnic drugiego rzędu: r 2i = r 1i - r 1(i-1), dla i > 1 Różnice drugiego rzędu powstają w analogiczny sposób z różnic pierwszego rzędu, jak różnice pierwszego rzędu powstają z wyrazów ciągu od i-tej różnicy pierwszego rzędu odejmujemy poprzedzającą ją, (i - 1)-szą różnicę. i 0 1 2 3 4 5 6 7 8 9 10 11 12... i 2 0 1 4 9 16 25 36 49 64 81 100 121 144... r 1 1 3 5 7 9 11 13 15 17 19 21 23... r 2 2 2 2 2 2 2 2 2 2 2 2...

Różnice rzędu drugiego tworzą już ciąg stały o wyrazach równych 2. Nie ma sensu liczyć różnic wyższych rzędów, ponieważ otrzymamy tylko wyrazy równe 0. W tabelce zaznaczyliśmy pierwsze wyrazy odpowiednio: ciągu kwadratów i 2 0 ciągu różnic pierwszego rzędu r 1i 1 ciągu różnic drugiego rzędu r 2i 2 Mając te trzy wartości możemy rekurencyjnie konstruować ciąg kolejnych kwadratów: a = 0, r 11 = 1, r 2 = 2, gdzie a 0 pierwszy wyraz ciągu kwadratów Dla i > 0 mamy: r 1i = r 1(i-1) + r 2 kolejna różnica pierwszego rzędu powstaje z poprzedniej przez dodanie różnicy drugiego rzędu a i = a i-1 + r 1i kolejny kwadrat powstaje z poprzedniego przez dodanie wyliczonej różnicy pierwszego rzędu Zwróć uwagę, iż wykorzystujemy tylko dodawanie, dzięki czemu nasz algorytm jest szybki. Jednakże podany algorytm nie jest stosowany w praktyce do wyznaczania wartości pierwiastka kwadratowego. Podajemy go tutaj tylko ze względów dydaktycznych.

ALGORYTM OBLICZANIA CAŁKOWITEGO PIERWIASTKA KWADRATOWEGO WERSJA NR 1 Wejście x liczba, której pierwiastek obliczamy, x 0, x ϵ R Wyjście: całkowity pierwiastek kwadratowy z x Elementy pomocnicze: i numery wyrazów ciągu kwadratów, i ϵc a wyraz ciągu kwadratów, a ϵ C r 1 różnica pierwszego rzędu, r 1 ϵ N r 2 różnica drugiego rzędu, r 2 ϵ N

Lista kroków: K01: a 0 ; pierwszy kwadrat 0 2 K02: r 1 1 ; początkowa wartość różnicy pierwszego rzędu K03: r 2 2 ; wartość różnic drugiego rzędu K04: i 0 ; numer pierwszego wyrazu K05: Dopóki a x wykonuj K06...K 08 ; szukamy pierwszego wyrazu a większego od x K06: a a + r 1 ; następny kwadrat K07: r 1 r 1 + r 2 ; wyliczamy nową różnicę pierwszego rzędu K08: i i + 1 ; następny numer K09: Zakończ z wynikiem i - 1 ; obliczamy pierwiastek całkowity

W pierwszym wierszu program odczytuje liczbę x. Następnie wyznacza jej całkowity pierwiastek kwadratowy i wypisuje go w wierszu drugim. Dodatkowo w wierszu trzecim program wypisuje kwadrat znalezionego pierwiastka kwadratowego dla celów porównawczych.

ROZWIĄZANIE NR 2 Druga metoda znajdowania całkowitego pierwiastka kwadratowego pochodzi od Izaaka Newtona (chociaż podobną metodę stosowali już starożytni Babilończycy). Jeśli mamy pewne przybliżenie p pierwiastka liczby x, to lepsze przybliżenie otrzymamy stosując wzór: p = 1/2 (p + x /p)

DLACZEGO TO DZIAŁA? ROZWAŻMY DWA PRZYPADKI: p < x Wtedy iloraz x / p jest większy od x i po dodaniu go do p i podzieleniu sumy przez 2 otrzymamy liczbę większą od poprzedniego p, która przybliża się od dołu do rzeczywistego pierwiastka. p > x Wtedy iloraz x / p jest mniejszy od x i po dodaniu go do p i podzieleniu sumy przez 2 otrzymamy liczbę mniejszą od poprzedniego p, która przybliża się od góry do rzeczywistego pierwiastka. Wynika z tego, iż w każdej iteracji otrzymujemy liczbę coraz bliższą wartości pierwiastka. Iterujemy dotąd, aż różnica pomiędzy dwoma kolejnymi przybliżeniami będzie mniejsza lub równa założonej dokładności ε w przypadku pierwiastków całkowitych jest to 1.

ALGORYTM OBLICZANIA CAŁKOWITEGO PIERWIASTKA KWADRATOWEGO WERSJA NR 2 Wejście x liczba, której pierwiastek obliczamy, x 0, xϵ C Wyjście: Całkowity pierwiastek kwadratowy z x Elementy pomocnicze: p 1, p 2 kolejne przybliżenia pierwiastka z x; p 1, p 2 ϵ C

Lista kroków: K01: Jeśli x > 1, to idź do K04 ; pierwiastki > 1 liczymy K02: p 2 x ; inne nie K03: Idź do K09 K04: p 1 0 ; zapewniamy p 1 - p 2 > 1 K05: p 2 x shr 1 ; pierwsze przybliżenie pierwiastka K06: Dopóki p 1 - p 2 > 1, wykonuj K07...K08 ; w pętli wyliczamy kolejne przybliżenia K07: p 1 p 2 ; zapamiętujemy bieżące przybliżenie K08: p 2 (p 2 + x div p 1 ) shr 1 ; wyliczamy nowe przybliżenie K09: Dopóki p 2 p 2 > x, wykonuj p 2 p 2-1 ; jeśli przybliżenie było od góry, zmniejszamy je K09: Zakończ z wynikiem p 2

W pierwszym wierszu program odczytuje liczbę x. Następnie wyznacza jej całkowity pierwiastek kwadratowy i wypisuje go w wierszu drugim. Dodatkowo w wierszu trzecim program wypisuje kwadrat znalezionego pierwiastka kwadratowego dla celów porównawczych.

ROZWIĄZANIE NR 3 Istnieje bardzo szybki algorytm wyznaczania wartości całkowitego pierwiastka kwadratowego, który wykorzystuje binarną reprezentację liczb czyli idealnie nadaje się do zastosowania dla danych komputerowych, które przecież są liczbami binarnymi. Algorytm wywodzi się z chińskiego abakusa i nie wymaga skomplikowanych działań arytmetycznych jedynie dodawania oraz przesuwania bitów. Dzięki tym zaletom może być z powodzeniem stosowany w prostych systemach mikrokontrolerów jednoukładowych.

ALGORYTM OBLICZANIA CAŁKOWITEGO PIERWIASTKA KWADRATOWEGO WERSJA NR 3 Wejście: x liczba, której pierwiastek obliczamy, x 0, x ϵ C Wyjście: Całkowity pierwiastek kwadratowy z x Elementy pomocnicze: m b zawiera maskę bitową z ustawionym jednym bitem. Maska jest 64 bitowa. p x obliczana wartość pierwiastka, p x ϵc

Lista kroków: K01: p x 0 ; początkowa wartość pierwiastka K02: m b 1 shl 62 ; maska z ustawionym drugim najstarszym bitem K03: Dopóki m b > x, wykonuj m b m b shr 2 ; szukamy najstarszej potęgi 4, mniejszej od x K04: Dopóki m b 0, wykonuj K05...K09 ; wyznaczamy kolejne bity pierwiastka K05: t p x + m b ; łączymy bit maski z przybliżeniem pierwiastka K06: Jeśli x < t, idź do K09 ; sprawdzamy, czy dany bit ma być ustawiony. K07: x x - t ; usuwamy bity z x K08: p x t + m b ; dodajemy bit maski do p x K09: p x p x shr 1 ; przesuwamy bity pierwiastka o 1 w prawo K09: m b m b shr 2 ; bity maski przesuwamy o 2 w prawo K10: Zakończ z wynikiem p x

W pierwszym wierszu program odczytuje liczbę x. Następnie wyznacza jej całkowity pierwiastek kwadratowy i wypisuje go w wierszu drugim. Dodatkowo w wierszu trzecim program wypisuje kwadrat znalezionego pierwiastka kwadratowego dla celów porównawczych.