Ciąg Powrotny to taki ciąg, który polega na zapisaniu kolejnych liczb naturalnych, ale jeśli zostanie wypisana liczba, która do tej pory w ciągu nie wystąpiła to należy rozpocząć liczenie od nowa.
Ciąg ma następującą postać: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, ...
Oto wyjaśnienie wyznaczania kolejnych wyrazów:
n | Wartość | Komentarz |
---|---|---|
1 | 1 | 1 wystąpiło pierwszy raz, więc następny wyraz to 1 |
2 | 1 | zwiększamy wartość |
3 | 2 | 2 wystąpiło pierwszy raz, więc następny wyraz to 1 |
4 | 1 | zwiększamy wartość |
5 | 2 | zwiększamy wartość |
6 | 3 | 3 wystąpiło pierwszy raz, więc następny wyraz to 1 |
7 | 1 | zwiększamy wartość |
Zauważmy, że po pierwszym wystąpieniu k-tej liczby następne wystąpienie jest po k wyrazach, potem kolejno po k+1, k+2, .. wyrazach. Ilustruje to poniższa tabelka w której oznaczone zostały liczby 2.
1 | 1 | 2 | 1 | 2 | 3 | 1 | 2 | 3 | 4 | .. |
---|
Opisywany ciąg liczb można przedstawić w postaci tabelki, gdzie przejście do następnego wiersza następuje w chwili rozpoczęcia liczenia od nowa.
1 | |||
1 | 2 | ||
1 | 2 | 3 | |
1 | 2 | 3 | 4 |
itd. |
W celu wyznaczenia n-tego wyrazu należy sprawdzić ile wyrazów znajduje się przed nim. Nie istnieje potrzeba wyznaczania ich wszystkich po kolei, ponieważ każdy wiersz zaczyna się od wyrazu 1. Z kolei i-ty wiersz ma dokładnie i-wyrazów. Wystarczy tak długo odejmować liczbę wyrazów w kolejnych wierszach, aż uzyskamy wartość, która może się znajdować w kolejnym wierszu. Jest to analogiczne do wyznaczania reszty z dzielenia - różnica tutaj polega na tym, że w każdej iteracji odejmujemy coraz większą liczbę, a w dzieleniu zawsze dzielnik.
Funkcja ntywyraz() akceptuje tylko jeden argument n. Wynikiem działania funkcji jest n-ta wartość Ciągu Powrotnego:
(2.) Z pierwszego wyrazu nie trzeba odejmować żadnej wartości. (3. - 5.) Odejmuj kolejne ilości elementów z kolejnych wierszy od wartości n. Na koniec (7.) należy zwrócić wartość n + 1, ponieważ wynikowa reszta jest z przedziału [0, i-1], gdzie i to numer wiersza w którym n-ta wartość się znajduje.
Poprzednia metoda jest efektywna do wyznaczania pojedynczego wyrazu, ale mało efektywna do wyznaczania k pierwszych wyrazów, ponieważ im większe n tym rośnie ilość iteracji potrzebna do wyznaczenia wartości elementu ciągu.
Istnieje możliwość wyznaczania kolejnego wyrazu na podstawie poprzedniego oraz znajomości numeru wiersza w którym się znajdujemy. W ten sposób gwarantowana jest złożoność liniowa wyznaczania k-wyrazów. Funkcja kwyrazow() to przykładowa implementacja, która zwraca tablicę k pierwszych wyrazów Ciągu Powrotnego.
(2.) Przygotuj tablice pod wynik, a następnie (3.) przypisz zmiennej n - aktualny wyraz, a zmiennej max - numer aktualnego wiersza. (4.) Kolejne elementy wyznaczamy w pętli: (5.) zapisz aktualny wyraz i (6.) jeśli jest to ostatni element w wierszu to (7.) ustaw aktualny wyraz na 1 i (8.) zwiększ numer wiersza. (9.) Jednak jeśli nie jest to ostatni element w wierszu to (10.) zwiększ wartość aktualnego elementu. Na koniec (13.) funkcja zwraca wskaźnik na tablicę, gdzie dane są przechowywane.
Poniższy fragment kodu prezentuje zastosowanie obydwu napisanych funkcji.
Napisz funkcję ntywyraz() w której zostanie wykorzystany wzór na sumę n pierwszych liczb naturalnych, aby przyśpieszyć pracę. Przetestuj napisaną funkcję.