Informatyczny kącik olimpijski
Samogenerujący się ciąg
W tym numerze Delty dużo uwagi poświęcono ciągowi EKG, który
zarówno z matematycznego, jak i z informatycznego punktu widzenia
przejawia wiele interesujących własności. W kąciku kontynuujemy temat
ciekawych ciągów liczbowych. Zajmiemy się zadaniem Ciąg z finału
II Olimpiady Informatycznej Gimnazjalistów, w którym poproszono
uczestników o wyznaczenie
-tego wyrazu pewnego ciągu, zwyczajowo
wiązanego z nazwiskiem matematyka Solomona Golomba.
Ciąg ten jest niemalejącą sekwencją liczb całkowitych dodatnich
taką
że
oznacza łączną liczbę wystąpień liczby
w tej sekwencji.
To już cała definicja; spróbujmy rozszyfrować, jak wygląda ten tajemniczy
ciąg.
Zacznijmy od początku, czyli od wyrazu
Ponieważ
więc w ciągu musi wystąpić co najmniej jedna jedynka,
a skoro ciąg jest niemalejący, to musi zaczynać się od jedynki, czyli
Przejdźmy teraz do
Otóż nie może być
gdyż w ciągu mamy dokładnie jedną jedynkę (
). Stąd
czyli – podobnie jak poprzednio – w ciągu jest co najmniej jedna
dwójka, więc
To oznacza, że w ciągu mamy łącznie
dwie dwójki, czyli
A zatem w ciągu mamy dwie trójki,
To z kolei oznacza, że mamy po trzy czwórki i piątki, czyli
nasz ciąg zaczyna się tak: 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5.
Widzimy, że możemy dalej rozumować w ten sposób; co więcej,
otrzymujemy algorytm na generowanie wyrazów ciągu Golomba. Startujemy
od
i
po czym dla każdego kolejnego
na koniec ciągu wstawiamy
wyrazów równych
(ciąg reprezentujemy w zwykłej tablicy). Za każdym razem dodajemy
więcej niż jeden wyraz, więc nigdy nie będziemy musieli „zgadywać” – kiedy
dojdziemy do indeksu
będziemy już znali
Kontynuujemy to
postępowanie, aż przypiszemy wartość
Koszt czasowy i, niestety,
także pamięciowy to
Za taki naturalny algorytm można było na
zawodach uzyskać 40% punktów.
Spróbujmy usprawnić ten algorytm, przede wszystkim pod względem
zapotrzebowania na pamięć. Kluczowe spostrzeżenie już właściwie
poczyniliśmy poprzednio: kiedy natrafiamy na wyraz
dopisujemy
na koniec ciągu pełne
nowych wyrazów, a tymczasem przesuwamy
się indeksem zaledwie o 1 (do
). A im dalej, tym
jest
większe. To oznacza, że istotnie rośnie nam „ogon” już obliczonych
wartości, które pozostają do przejrzenia. Algorytm może się zakończyć, gdy
już przetworzony fragment ciągu wraz z tym ogonem ma co najmniej
wyrazów. Ponieważ ogon jest długi, więc będziemy przechowywać
w tablicy tylko pewną początkową liczbę wyrazów ciągu, a ponadto będziemy
pamiętać długość pozostałego ogona.
Oznaczmy przez
sumę
początkowych wyrazów ciągu
(niech
). W tablicy musimy przechowywać jedynie
pierwsze
wyrazów ciągu, takich że
Jak duże musi
być to
? Sprawdźmy eksperymentalnie! Za pomocą poprzedniego
algorytmu obliczamy, że
co pozwala zgadnąć, iż
Przy tym założeniu mamy, że

Stąd
dla
rzędu
Jest to istotnie lepiej niż
poprzednio, a sam algorytm pozostał prosty: obliczamy początkowy fragment
ciągu długości rzędu
(dokładną długość możemy wyznaczyć
eksperymentalnie, rozważając górne ograniczenie na
), po czym
obliczamy kolejne
do momentu, gdy
; wówczas
Za takie podejście można było otrzymać 70% punktów;
pozwala ono obliczyć np.
To oznacza, że musi
dać się jeszcze lepiej! W poprzedniej metodzie z
-elementowego
początkowego fragmentu ciągu wnioskowaliśmy o
wyrazach ciągu.
Teraz zwiększymy tę liczbę.
Załóżmy, że mamy obliczone
Wówczas dla każdego
wiemy, że na pozycjach
w naszym
ciągu pojawia się liczba
To z kolei oznacza, iż każda z
liczb
występuje w ciągu
razy. Nasz ciąg wygląda
zatem tak: jedno wystąpienie liczby
po dwa wystąpienia liczb
po trzy wystąpienia liczb
itd. W ten
sposób na podstawie pierwszych
wyrazów ciągu jesteśmy w stanie
ustalić
początkowych wyrazów ciągu. Liczbę
szacujemy podobnie jak poprzednio:

Stąd warunek
zachodzi już dla
rzędu
Dokładny
opis algorytmu opartego na wartościach
podobny do poprzedniego,
pozostawiamy Czytelnikowi. To jest rozwiązanie wzorcowe tego zadania; za
jego pomocą obliczamy, że np.
Na koniec
winni jesteśmy Czytelnikowi drobne sprostowanie: otóż odgadnięte
oszacowanie
jest nieprawdziwe, lecz nie jest zbyt odległe
od poprawnego. W rzeczywistości
przy czym
czyli
jest rzędu
Po więcej
informacji na ten temat odsyłamy do Internetowej Encyklopedii Ciągów
Liczbowych, którą, swoją drogą, polecamy wszystkim miłośnikom ciekawych
ciągów.
I jeszcze pytanie do Czytelnika: czy można dalej usprawniać podane
algorytmy, wprowadzając odpowiednie ciągi pomocnicze
itd.?