You are on page 1of 1

Informatyczny kcik olimpijski (28): Maszyna Fibonacciego

W tym kciku zajmiemy si zadaniem z finau Potyczek


Algorytmicznych 2009.
Wemy funkcj F zwracajc liczby Fibonacciego, tzn.
F(0) = 0, F(1) = 1 oraz F(m) = F(m1) + F(m2)
dla m 2. Mamy cig rejestrw (i1, i2, . . . , in),
pocztkowo ustawionych na zera. W zadaniu chodzi
o zaimplementowanie dwch operacji:
dla podanych a i b dodanie jedynki do kadego z rejestrw
ia, ia+1, . . . , i
b1
, i
b
,
dla podanych a i b wypisanie reszty z dzielenia wartoci
F(ia) + F(ia+1) + . . . + F(i
b1
) + F(i
b
) przez P = 10
9
+ 7.
Wykonamy cznie k operacji tych dwch typw.
Zacznijmy od jakiegokolwiek poprawnego rozwizania.
Naturalnie, atwo w czasie O(n) wykona pierwsz operacj
poprzez dodanie odpowiednich jedynek. Druga operacja
zajmuje w takim razie czas O(ia + ia+1 + . . . + i
b
), gdy
F(x) mod P obliczamy atwo w czasie O(x), a poniewa
iy k, wic daje to zoono O(n k). czny koszt takiego
algorytmu to O(n k
2
).
Mdrzej jednak bdzie pamita od razu wartoci
F(iy) mod P zamiast samych iy. Aby mc zwiksza
iy o jeden, potrzebne nam s tak naprawd
dwie kolejne wartoci F, np. Ay = F(iy) mod P
oraz By = F(iy + 1) mod P. Zaczniemy wic od
Ay = 0, By = 1 dla y = 1, 2, . . . , n. W ten sposb
zarwno pierwsz (podstawiajc, dla a y b,
(Ay, By) = (By, (Ay + By) mod P)), jak i drug (zwracajc
(Aa + . . . + A
b
) mod P) operacj wykonujemy w czasie O(n)
i dostajemy sumaryczn zoono O(n k).
Aby jeszcze przyspieszy rozwizanie, kluczowe jest
spostrzeenie, e przeksztacenie (x, y) (y, x + y) jest
liniowe, a wic ma swoj macierz L (rozmiaru 2 2), tzn.
tak macierz, e L (x, y) = (y, x + y). Ponadto, k-krotne
zoenie takiego przeksztacenia te jest liniowe i ma
macierz L
k
(oczywicie te rozmiaru 2 2). Dodatkowo,
moemy bezkarnie przyj, e n = 2
m
dla m naturalnego.
W przeciwnym bowiem razie zwikszamy n do najbliszej
potgi dwjki, co nie zmienia zoonoci (bo n wzrasta
co najwyej dwukrotnie), i pniej po prostu nie uywamy
w ogle czci rejestrw. Wyobramy sobie teraz pene
drzewo binarne o 2
m+1
1 wierzchokach (patrz rysunek),
w ktrego liciach mamy wartoci Ay i By dla kolejnych y
z przedziau [1, 2
m
].
W kadym wle v zapamitamy informacj o:
synach tego wierzchoka w drzewie: lewyv i prawyv (dla
lici nieokrelone),
przedziale rejestrw bdcych jego potomkami w drzewie,
tj. [lv, pv],
sumach wartoci Ay i By po tych rejestrach, odpowiednio:
A

v
i B

v
,
macierzy przeksztacenia Lv, ktre zostao wykonane na
caym przedziale rejestrw [lv, pv].
Pocztkowo, dla wszystkich v, Lv jest macierz
identycznoci. W momencie dodawania jedynki do rejestrw
z przedziau [a, b], zmieniamy A

v
, B

v
i Lv dla pewnych
wierzchokw, a konkretnie dla takich, eby ich przedziay
potomkw sumoway si w sposb rozczny (biorc pod
uwag tylko zawarte w przedziale liczby cakowite) do
przedziau [a, b], np. [2, 7] = [2, 2] [3, 4] [5, 6] [7, 7].
Tych przedziaw wybierzemy O(m), wywoujc
podziel(a, b, korze) w poniszym pseudokodzie
zakadamy wykonywanie dziaa modulo P:
przy(v, X)
(A

v
, B

v
) := X (A

v
, B

v
)
Lv := Lv X
podziel(a, b, v)
1 if (a = lv) and (b = pv) then
2 przy(v, L)
3 else
4 przy(lewyv, Lv)
5 przy(prawyv, Lv)
6 Lv := id2
7 if a p
lewyv
then
8 podziel(a, min(b, p
lewyv
), lewyv)
9 if b lprawyv
then
10 podziel(max(a, lprawyv
), b, prawyv)
11 A

v
:= A

lewyv
+ A

prawyv
12 B

v
:= B

lewyv
+ B

prawyv
Dlaczego to dziaa? Po pierwsze, koczy si, bo w kadym
wywoaniu podziel zachodzi: [a, b] [lv, pv], a dla
lici mamy lv = pv, wic zachodzi warunek z linii
pierwszej i funkcja nie wywouje si wicej rekurencyjnie.
Po drugie, rzeczywicie rozkada przedzia [a, b] na
sum przedziaw, poniewa p
lewyv
+ 1 = lprawyv
,
wic przedziay [a, min(b, p
lewyv
)] i [max(a, lprawyv
), b]
(lub jeden z nich, gdy nie zachodzi ktry z warunkw
z linii 7 i 9) pokrywaj cay przedzia [a, b]. Po trzecie
wreszcie, po pierwszym takim wywoaniu, ktre powoduje
rozgazienie rekurencyjne (tzn. wykonuj si obie linie
8 i 10), w kadym kolejnym zachodzi co najmniej jeden
z warunkw: a = lv lub b = pv. W takim razie kade
kolejne rozgazienie rekurencyjne powoduje, e w co
najmniej jednym z dwch wywoa rekurencyjnych zachodzi
zarwno a = lv, jak i b = pv, a wic ta ga natychmiast
si koczy. Std, wywoa funkcji podziel moe by
co najwyej 4m + 1 (jedno w korzeniu oraz w kadym
z dwch poddrzew po 2m: m takich, ktre od razu si
kocz, i m kontynuowanych), a wic O(m). To koczy
uzasadnienie, e potrafimy za pomoc takiej struktury
w czasie O(log n) wykona pierwszy typ operacji. Typ drugi
obsugujemy analogicznie, z t rnic, e odpowiednia
funkcja podziel2 zwraca dan sum. W tym celu linia
druga zostaje zmieniona na returnA

v
, a suma wynikw
z podwywoa podziel2 z linii 8 i 10 zostaje zwrcona
w dodatkowej linii 13 jako wynik wywoania teje funkcji.
Dowd poprawnoci i zoonoci czasowej jest analogiczny.
Std czny czas wykonania wynosi O(n + k log n) przy
zuyciu pamici rzdu O(n), gdy drzewo ma co najwyej
4n wierzchokw i w kadym przechowujemy sta ilo
informacji.
Tomasz KULCZYSKI
11

You might also like