Sito Eratostenesa to algorytm za pomocą, którego jesteśmy w stanie w szybki sposób wyznaczyć liczby pierwsze z przedziału od 2 do n, gdzie n jest górną granicą przedziału. Stworzenie algorytmu przypisuje się Grekowi, Eratostenosowi z Cyreny.
Tworzymy tablicę i wypełniamy ją jedynkami. Bierzemy najmniejszy indeks (czyli dwa) i ustawiamy wartości wszystkich komórek, których indeksy są wielokrotnościami dwójki na fałsz. W dalszej kolejności postępujemy tak z następnym niewykreślonym indeksem, czyli trójką i analogicznie jak w przypadku dwójki ustawiamy wartości komórek o indeksach równych i*3 na fałsz.
W ten sposób postępujemy, dopóki obierany indeks będzie mniejszy lub równy pierwiastkowi z n.
Jeżeli pod danym indeksem jest 1, wówczas wykreślamy wielokrotności liczby z indeksu (dla 2 wykreślamy 4,6,8,10,12…1000000 ),zamieniamy wartości "indeksów" na 0.
Sito bardzo dobrze opisane jest na stronie https://www.algorytm.edu.pl/algorytmy-maturalne/sito-eratostenesa.html
Zadanie Dyzio: https://themis.ii.uni.wroc.pl/202324SP76KL7/DYZIO
Na wejściu dostajemy (w najgorszym wypadku) 20 000 zestawów zapytań o przedziały , .Dla każdego z zapytań chcemy odpowiedź na pytanie: ,Ile jest liczb pierwszych niemniejszych od a i niewiększych od b?''.
Pierwszą opcją byłoby policzenie wyniku ręcznie dla każdego przedziału.
Dla każdego przedziału , dla każdej liczby naturalnej z tego przedziału liczymy, czy jest ona liczbą pierwszą. Umiemy już dla liczby sprawdzić w mniej więcej operacjach, czy jest pierwsza.
Przykładowy kod mógłby wyglądać następująco:
W powyższym rozwiązaniu dla każdego z (być może) 20000 przedziałów, dla każdej liczby z przedziału (przedział może mieć 1000000 liczb!) sprawdzamy, czy taka liczba jest pierwsza (co też zajmuje czas jako, że - od 1 do 1000 operacji).
Łącznie więc ten program wykona mniej więcej $20000 * 1000000 * 10000000000000 operacji. Bardzo dużo.
Wiemy już, jak policzyć sito Eratostenesa - a zatem jak w mniej-więcej operacjach wiedzieć o każdej liczbie, czy jest pierwsza, czy też nie.
Możemy więc policzyć sito Eratostenesa, a później wczytując zapytanie (przedział) wyliczać, ile liczb pierwszych się tam pojawiło.
W najgorszym przypadku policzymy sito w operacjach, a następnie dla każdego z zapytań przejdziemy pętlą po milionie liczb (od 1 do 1000000). Wciąż jest to mniej-więcej operacji.
Z pomocą przychodzi inny temat omawiany na zajęciach: sumy prefiksowe. Mając policzone sito, możemy policzyć (i zapamiętać w tablicy) dla każdej wartości , ile jest liczb pierwszych niewiększych od .
Następnie dostając zapytanie o przedział wystarczy znaleźć w tablicy, ile jest liczb pierwszych nie większych od oraz ile jest takich, które są mniejsze od (niewiększe od ).
Wartości początkowych pól obu tablic powinny wyglądać tak:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
0 | 0 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 4 | 4 | 5 | 5 | 6 | 6 | 6 | 6 |
Liczba operacji potrzebna na policzenie wartości w drugiej tablicy to mniej więcej . Mając sito Eratostenesa policzone w tablicy ,sito'', drugą tablicę liczymy następująco:
Wynikiem dla przedziału jest ilePierwszych[b]-ilePierwszych[a-1];
https://themis.ii.uni.wroc.pl/202324SP76KL7/E_FAC2
W zadaniu dostajemy zapytań, każde składa się z jednej liczby. Należy wypisać po kolei czynniki pierwsze tej liczby.
Oczywiście podobnie jak w poprzednim zadaniu, gdy dostaniemy zapytanie o liczbę , możemy dla każdej liczby sprawdzać czy jest ona dzielnikiem , następnie wypisywać ją i zmniejszać . Kod mógłby wyglądać tak:
Podobnie jak w poprzednim zadaniu - takie rozwiązanie jest poprawne, ale za wolne.
Być może nie musimy za każdym razem szukać dzielnika…
Wyobraźmy sobie, że licząc sito zapamiętujemy więcej niż tylko zera i jedynki. Że dla liczby złożonej, zapamiętamy jej najmniejszy dzielnik.
Jak to zrobić? Wystarczy dla każdej liczby złożonej zapamiętać, jaka liczba pierwsza ją ,skreśliła''.
Przykładowy początek tablicy:
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 1 | 2 | 1 | 2 | 3 | 2 | 1 | 2 | 1 | 2 | 3 | 2 | 1 | 2 |
Wartość w 15 to 3, gdyż 3 jest najmniejszym pierwszym dzielnikiem 15. 3 ,skreśliło'' 15.
Mając taką tablicę i zapytanie o dzielniki liczby możemy po prostu wypisać , a następnie zmniejszyć I wykonywać tak aż stanie się jedynką.
Jak policzyć taką tablicę?