BOI 2016
CEOI 2017
BOI 2018
BOI 2019
BOI 2020
CEOI 2020
Star Trek
Dane jest () identycznych drzew
o wierzchołkach ().
Należy policzyć, na ile sposobów można wybrać par wierzchołków
w taki sposób, aby po dodaniu dodatkowych krawędzi
między -tym wierzchołkiem w -tym drzewie,
a -tym wierzchołkiem w -wszym drzewie
dla każdego ,
gracz zaczynający ruch z pionkiem w wierzchołku w drzewie o numerze
wygrał następującą grę.
Gra jest dwuosobowa przeprowadzona na wyżej zdefiniowanym drzewie ,
gdzie wierzchołek jest zadany jako para oznaczająca,
że wierzchołek znajduje się w -tym drzewie
w wierzchołku o numerze .
W jednym ruchu gracz może przesunąć pionek wzdłuż krawędzi,
ale nie może wrócić do takiej pary , która była już odwiedzona.
Gracze grają na przemian i przegrywa ten gracz, który nie może już wykonać ruchu.
Należy założyć, że gracze grają optymalnie.
Liczbę takich pasujących par wierzchołków
(nazwanymi dodatkowymi krawędziami)
należy wypisać modulo .
Podzadanie 2
Jeżeli , to gracz zaczynający grę zawsze może wygrać.
Przykładową jego strategią może być zawsze używanie
krawędzi z . Wtedy drugi gracz zawsze musi przejść
przez dodatkową krawędź, chyba że taka już nie istnieje
(i wtedy drugi gracz przegrywa).
Istnieje więc sposobów na dodanie dodatkowych krawędzi.
Liczbę można policzyć szybkim potęgowaniem
w czasie .
Gra dla dowolnego drzewa
Mając dane dowolne drzewo zakorzenione w pewnym wierzchołku, w czasie liniowym
można policzyć dla każdego wierzchołka (na przykład DFS-em)
informację, czy wygra gracz zaczynający z pionkiem w tym wierzchołku
przy dodatkowym założeniu, że pionek nie może przejść do ojca tego wierzchołka
(czyli można się poruszać tylko w poddrzewie tego wierzchołka),
w następujący sposób:
-
Jeżeli ten wierzchołek jest liściem, to gracz zaczynający w tym wierzchołku
jest w stanie przegrywającym,
ponieważ nie może wykonać żadnego ruchu.
-
Jeżeli wierzchołek nie jest liściem oraz istnieje syn, który jest stanem przegrywającym,
to ten wierzchołek jest w stanie wygrywającym,
ponieważ można przesunąć pionek w kierunku tego syna.
-
Jeżeli wierzchołek nie jest liściem oraz każdy jego syn jest stanem wygrywającym,
to ten wierzchołek jest w stanie przegrywającym,
ponieważ nieważne jaki ruch się wykona, przeciwny gracz będzie w stanie wygrywającym,
więc potrafi pociągnąć grę do jego wygranej.
Można dzięki temu algorytmowi w czasie sprawdzić,
czy gracz zaczynający z pionkiem w danym wierzchołku
wygra grę przy założeniu, że gracze grają optymalnie.
Podzadanie 3
Przy ograniczeniach
wystarczy wypróbować każdą możliwą dodatkową krawędź
i powyższym algorytmem sprawdzić, czy gracz zaczynający grę ma stan wygrywający.
Krytyczne stany przegrywające
Zamiast wyliczać całe drzewo powstałe przez kopii drzewa ,
lepiej jest się skupić na spreprocessowaniu odpowiednich informacji drzewa ,
które będzie można „łączyć” pomiędzy kolejne kopie drzewa .
Dla danych dodatkowych krawędzi
,
jeżeli wiadomo, czy wierzchołek drzewa jest wygrywający,
czy przegrywający, można policzyć w jaki sposób dodanie dodatkowej krawędzi
wpłynie na stany wierzchołków dla .
Ogólniej można to sobie wyobrażać jako dodanie do pewnego wierzchołka
zakorzenionego drzewa w wierzchołku
nowego syna o pewnym stanie (przegrywającym lub wygrywającym) i wyliczenie
nowego stanu korzenia drzewa .
Taki proces będzie wykonywany łącznie razy.
Z definicji stanów w algorytmie gry dla dowolnego drzewa wynika,
że stan wierzchołka zmieni się tylko wtedy, gdy oraz są stanami przegrywającymi
(i wtedy stanie się stanem wygrywającym).
Wtedy ojciec wierzchołka (oznaczany jako ) zmieni swój stan tylko wtedy,
gdy jest stanem wygrywającym.
Analogicznie można rozpatrywać kolejne przodki wierzchołka .
W takim razie, jeżeli stany wierzchołków
są na zmianę przegrywające, wygrywające, przegrywające, ...,
to podczepienie do wierzchołka sprawi, że korzeń zmieni swój stan,
o ile jest stanem przegrywającym
(i wtedy będzie nazywany krytycznym stanem przegrywającym dla korzenia ).
Niech zbiór wszystkich takich , których łańcuszek stanów do korzenia jest takiej postaci,
będzie oznaczony jako .
Da się ten zbiór wyznaczyć dla konkretnego w czasie .
Podzadanie 4
Zadanie przy ograniczeniach można rozwiązać w następujący sposób.
Niech -- zbiór wierzchołków , dla których rozpoczęcie gry z pionkiem w tym wierzchołku
jest stanem wygrywającym,
oraz -- zbiór wierzchołków , dla których rozpoczęcie gry z pionkiem w tym wierzchołku
jest stanem przegrywającym.
Te zbiory można wyznaczyć w złożoności .
Niech drzewo o numerze będzie (ukorzenione w wierzchołku ),
a drzewo o numerze będzie (można dowolnie wybrać korzeń).
Nadal zachodzi , ale zostały odróżnione dla zwięzłości oznaczeń.
Jeżeli korzeń jest w stanie wygrywającym,
to po dodaniu dodatkowej krawędzi zmieni swój stan tylko wtedy,
gdy do wierzchołka z zostanie doczepiony
jakiś korzeń , który jest w stanie przegrywającym.
Dlatego wynik (liczba sposobów dodania dodatkowej krawędzi,
aby korzeń był w stanie wygrywającym)
wynosi
(korzenie wygrywające można doczepić gdziekolwiek,
a przegrywające tylko do wierzchołków spoza ).
Jeżeli korzeń jest w stanie przegrywającym,
to tylko doczepienie korzenia przegrywającego
do wierzchołka sprawi, że korzeń zmieni swój stan na wygrywający,
dlatego wynik wynosi .
Podzadanie 5
Dla można zastosować podejście z podzadania 4,
ale należy przyśpieszyć rozwiązanie,
czyli szybciej wyznaczyć zbiory oraz
(nie trzeba przyśpieszyć wyznaczania , ponieważ jest wyznaczany
w czasie liniowym).
Można to zrobić techniką nazywaną przekorzenieniem drzewa. Należy zacząć od użycia algorytmu z gry dla dowolnego drzewa i policzyć wynik dla każdego poddrzewa przy założeniu, że korzeniem jest , a następnie DFS-em zmieniać korzeń na każdy inny wierzchołek. W momencie, gdy jest zmieniany korzeń z na (gdzie jest sąsiadem ), to mogą się zmienić tylko dwa stany poddrzew (tylko wierzchołków oraz ), ponieważ reszta poddrzew nie zmieni swojego zbioru wierzchołków. Wystarczy więc przy przekorzenieniu ponownie obliczyć stany gry dla dwóch wierzchołków (a przy wyjściu z DFS-a cofnąć te zmiany). Otrzymujemy dzięki temu wyznaczanie zbiorów oraz w czasie , co rozwiązuje to podzadanie także w czasie .
Podzadanie 6
Przy , można policzyć następującą wartość.
Niech oznacza liczbę sposobów wybrania wierzchołka początkowego oraz wybrania dodatkowych krawędzi, aby gracz zaczynający przegrał, przy założeniu, że jest identycznych drzew i można zacząć z dowolnego wierzchołka.
Wiadomo już, że na sposobów można zmienić stan wybranego wierzchołka początkowego (ponieważ wystarczy dodać krawędź ze stanu przegrywającego do wierzchołka ze stanem krytycznym).
Aby stał się stanem wygrywającym, należy albo zmienić jego stan, albo nie zmienić, w zależności od tego, jaki jest stan przed dodaniem dodatkowej krawędzi. Dlatego liczba sposobów , aby wierzchołek początkowy był przegrywający, wynosi gdy oraz gdy , przy czym .
Mamy więc
gdzie oraz można spreprocessować w .
Szukana liczba w zadaniu wynosi (pionek jest początkowo położony w wierzchołku drzewa ).
Mając wyznaczone w liczby
można wyznaczyć w czasie podanym wzorem.
Otrzymujemy więc rozwiązanie o złożoności czasowej .
Podzadanie 7
Gdy oraz nie ma dodatkowego ograniczenia na ,
można zastosować powyższe rozwiązanie,
ale przyśpieszając wyznaczanie liczności zbiorów
za pomocą przekorzenienia,
tak jak w podzadaniu 5.
Podzadanie 8
Gdy nie ma dodatkowych ograniczeń,
w porównaniu do poprzedniego zadania,
należy szybciej wyznaczyć liczbę .
Znając wartość oraz ,
można wyznaczyć wzór na wartość .
Dzięki temu można skorzystać z techniki analogicznej do szybkiego potęgowania do obliczenia ,
czyli na przykład poprzez wyznaczenie liczb i domnażając te potęgi, których bity są zapalone w .
Alternatywnie, swoim ulubionym sposobem można wyprowadzić
wzór na postać jawną rekurencji liniowej ,
otrzymując wzór
dla ,
co można wyliczyć szybkim potęgowaniem oraz odwrotnością modulo.