Przeskocz do treści

Delta mi!

Informatyczny kącik olimpijski

Samogenerujący się ciąg

Jakub Radoszewski

o artykule ...

  • Publikacja w Delcie: maj 2011
  • Publikacja elektroniczna: 04-05-2011

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 math-tego wyrazu pewnego ciągu, zwyczajowo wiązanego z nazwiskiem matematyka Solomona Golomba.

Ciąg ten jest niemalejącą sekwencją liczb całkowitych dodatnich math taką że math oznacza łączną liczbę wystąpień liczby math 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 math Ponieważ math 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 math Przejdźmy teraz do math Otóż nie może być math gdyż w ciągu mamy dokładnie jedną jedynkę ( math). Stąd math czyli – podobnie jak poprzednio – w ciągu jest co najmniej jedna dwójka, więc math To oznacza, że w ciągu mamy łącznie dwie dwójki, czyli math A zatem w ciągu mamy dwie trójki, math 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 math i  math po czym dla każdego kolejnego math na koniec ciągu wstawiamy math wyrazów równych math (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 math będziemy już znali math Kontynuujemy to postępowanie, aż przypiszemy wartość math Koszt czasowy i, niestety, także pamięciowy to math  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 math dopisujemy na koniec ciągu pełne math nowych wyrazów, a tymczasem przesuwamy się indeksem zaledwie o 1 (do math). A im dalej, tym math 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 math 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 math  sumę math  początkowych wyrazów ciągu math (niech math ). W tablicy musimy przechowywać jedynie pierwsze math  wyrazów ciągu, takich że math  Jak duże musi być to math ? Sprawdźmy eksperymentalnie! Za pomocą poprzedniego algorytmu obliczamy, że math co pozwala zgadnąć, iż math Przy tym założeniu mamy, że

display-math

Stąd math  dla math  rzędu math  Jest to istotnie lepiej niż poprzednio, a sam algorytm pozostał prosty: obliczamy początkowy fragment ciągu długości rzędu math (dokładną długość możemy wyznaczyć eksperymentalnie, rozważając górne ograniczenie na math), po czym obliczamy kolejne math  do momentu, gdy math ; wówczas math Za takie podejście można było otrzymać 70% punktów; pozwala ono obliczyć np.  math To oznacza, że musi dać się jeszcze lepiej! W poprzedniej metodzie z math -elementowego początkowego fragmentu ciągu wnioskowaliśmy o math  wyrazach ciągu. Teraz zwiększymy tę liczbę.

Załóżmy, że mamy obliczone math  Wówczas dla każdego math wiemy, że na pozycjach math  w naszym ciągu pojawia się liczba math To z kolei oznacza, iż każda z math liczb math występuje w ciągu math  razy. Nasz ciąg wygląda zatem tak: jedno wystąpienie liczby math  po dwa wystąpienia liczb math po trzy wystąpienia liczb math  itd. W ten sposób na podstawie pierwszych math  wyrazów ciągu jesteśmy w stanie ustalić math początkowych wyrazów ciągu. Liczbę math szacujemy podobnie jak poprzednio:

display-math

Stąd warunek math  zachodzi już dla math  rzędu math  Dokładny opis algorytmu opartego na wartościach math podobny do poprzedniego, pozostawiamy Czytelnikowi. To jest rozwiązanie wzorcowe tego zadania; za jego pomocą obliczamy, że np. math Na koniec winni jesteśmy Czytelnikowi drobne sprostowanie: otóż odgadnięte oszacowanie math jest nieprawdziwe, lecz nie jest zbyt odległe od poprawnego. W rzeczywistości math przy czym math czyli math jest rzędu math 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 math  itd.?