Opis
BOI 2016
Bosses
Park
Spiral
Cities
Maze
Swap
CEOI 2017
Skierowanie dróg
Pewny zakład
Pułapka Mariusza
Budujemy mosty
Pościg Mariusza
Palindromiczny podział
BOI 2018
Miłosny wielokąt
Marsjańskie DNA
Problemy dżdżownicy
Prąd przemienny
Genetyka
Ścieżki
BOI 2019
Flash Memory
Nautilus
Alpine Valley
Tom's Kitchen
Necklace
Olympiads
BOI 2020
Kolory
Mieszanki
Joker
Graf
Wioska
Wirusy
CEOI 2020
Fajny płot
Drogi
Star Trek
Napój Wielkiej Potęgi
Wiosenne porządki
Szachowa gorączka

Star Trek

Dane jest D+1 (1D1018) identycznych drzew G o wierzchołkach 1,2,,n (2n105). Należy policzyć, na ile sposobów można wybrać D par wierzchołków (A0,B0),(A1,B1),,(AD1,BD1) w taki sposób, aby po dodaniu dodatkowych krawędzi między Ai-tym wierzchołkiem w i-tym drzewie, a Bi-tym wierzchołkiem w (i+1)-wszym drzewie dla każdego 0i<D, gracz zaczynający ruch z pionkiem w wierzchołku 1 w drzewie o numerze 0 wygrał następującą grę.

Gra jest dwuosobowa przeprowadzona na wyżej zdefiniowanym drzewie T, gdzie wierzchołek jest zadany jako para (i,v) oznaczająca, że wierzchołek znajduje się w i-tym drzewie (0iD) w wierzchołku G o numerze v (1vn). W jednym ruchu gracz może przesunąć pionek wzdłuż krawędzi, ale nie może wrócić do takiej pary (i,v), 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) (A0,B0),(A1,B1),,(AD1,BD1) należy wypisać modulo 109+7.

Podzadanie 2

Jeżeli n=2, to gracz zaczynający grę zawsze może wygrać. Przykładową jego strategią może być zawsze używanie krawędzi z G. Wtedy drugi gracz zawsze musi przejść przez dodatkową krawędź, chyba że taka już nie istnieje (i wtedy drugi gracz przegrywa). Istnieje więc 4D sposobów na dodanie dodatkowych krawędzi. Liczbę 4Dmod(109+7) można policzyć szybkim potęgowaniem w czasie O(logD).

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:

Można dzięki temu algorytmowi w czasie O(n) sprawdzić, czy gracz zaczynający z pionkiem w danym wierzchołku r wygra grę przy założeniu, że gracze grają optymalnie.

Podzadanie 3

Przy ograniczeniach n100,D=1 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 D+1 kopii drzewa G, lepiej jest się skupić na spreprocessowaniu odpowiednich informacji drzewa G, które będzie można „łączyć” pomiędzy kolejne kopie drzewa G.

Dla danych dodatkowych krawędzi (A0,B0),(A1,B1),,(AD1,BD1), jeżeli wiadomo, czy wierzchołek (1,B0) drzewa T jest wygrywający, czy przegrywający, można policzyć w jaki sposób dodanie dodatkowej krawędzi (A0,B0) wpłynie na stany wierzchołków (0,v) dla vG.

Ogólniej można to sobie wyobrażać jako dodanie do pewnego wierzchołka v zakorzenionego drzewa G w wierzchołku r nowego syna u o pewnym stanie (przegrywającym lub wygrywającym) i wyliczenie nowego stanu korzenia drzewa G. Taki proces będzie wykonywany łącznie D razy.

Z definicji stanów w algorytmie gry dla dowolnego drzewa wynika, że stan wierzchołka v zmieni się tylko wtedy, gdy v oraz u są stanami przegrywającymi (i wtedy v stanie się stanem wygrywającym). Wtedy ojciec wierzchołka v (oznaczany jako parent(v)) zmieni swój stan tylko wtedy, gdy parent(v) jest stanem wygrywającym. Analogicznie można rozpatrywać kolejne przodki wierzchołka v. W takim razie, jeżeli stany wierzchołków v,parent(v),parent(parent(v)),...,r są na zmianę przegrywające, wygrywające, przegrywające, ..., to podczepienie u do wierzchołka v sprawi, że korzeń zmieni swój stan, o ile u jest stanem przegrywającym (i wtedy v będzie nazywany krytycznym stanem przegrywającym dla korzenia r). Niech zbiór wszystkich takich v, których łańcuszek stanów do korzenia jest takiej postaci, będzie oznaczony jako Cr. Da się ten zbiór wyznaczyć dla konkretnego r w czasie O(n).

Podzadanie 4

Zadanie przy ograniczeniach n1000,D=1 można rozwiązać w następujący sposób.

Niech W -- zbiór wierzchołków G, dla których rozpoczęcie gry z pionkiem w tym wierzchołku jest stanem wygrywającym, oraz L -- zbiór wierzchołków G, 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 O(n2).

Niech drzewo o numerze 0 będzie G0 (ukorzenione w wierzchołku 1), a drzewo o numerze 1 będzie G1 (można dowolnie wybrać korzeń). Nadal zachodzi G0=G1=G, ale zostały odróżnione dla zwięzłości oznaczeń.

Jeżeli korzeń G0 jest w stanie wygrywającym, to po dodaniu dodatkowej krawędzi zmieni swój stan tylko wtedy, gdy do wierzchołka z C1 zostanie doczepiony jakiś korzeń G1, który jest w stanie przegrywającym. Dlatego wynik (liczba sposobów dodania dodatkowej krawędzi, aby korzeń T był w stanie wygrywającym) wynosi n|W|+(n|C1|)|L| (korzenie wygrywające G1 można doczepić gdziekolwiek, a przegrywające tylko do wierzchołków spoza C1).

Jeżeli korzeń G0 jest w stanie przegrywającym, to tylko doczepienie korzenia przegrywającego G1 do wierzchołka C1 sprawi, że korzeń G0 zmieni swój stan na wygrywający, dlatego wynik wynosi |C1||L|.

Podzadanie 5

Dla D=1 można zastosować podejście z podzadania 4, ale należy przyśpieszyć rozwiązanie, czyli szybciej wyznaczyć zbiory W oraz L (nie trzeba przyśpieszyć wyznaczania C1, 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 r=1, a następnie DFS-em zmieniać korzeń na każdy inny wierzchołek. W momencie, gdy jest zmieniany korzeń z r1 na r2 (gdzie r2 jest sąsiadem r1), to mogą się zmienić tylko dwa stany poddrzew (tylko wierzchołków r1 oraz r2), 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 W oraz L w czasie O(n), co rozwiązuje to podzadanie także w czasie O(n).

Podzadanie 6

Przy n1000,D105, można policzyć następującą wartość.

Niech LD 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 D+1 identycznych drzew i można zacząć z dowolnego wierzchołka.

Wiadomo już, że na |Cv|LD1 sposobów można zmienić stan wybranego wierzchołka początkowego v (ponieważ wystarczy dodać krawędź ze stanu przegrywającego do wierzchołka ze stanem krytycznym). Aby v stał się stanem wygrywającym, należy albo zmienić jego stan, albo nie zmienić, w zależności od tego, jaki jest stan v przed dodaniem dodatkowej krawędzi. Dlatego liczba sposobów LD,v, aby wierzchołek początkowy v był przegrywający, wynosi |Cv|LD1 gdy vW oraz n2D|Cv|LD1 gdy vL, przy czym L0=|L|.

Mamy więc LD=vLD,v=vW|Cv|LD1+vL(n2D|Cv|LD1)=|L|n2D+(vW|Cv|vL|Cv|)LD1, gdzie |L|n2D oraz (vW|Cv|vL|Cv|) można spreprocessować w O(n+logD).

Szukana liczba w zadaniu wynosi N2DLD,1 (pionek jest początkowo położony w wierzchołku 1 drzewa 0).

Mając wyznaczone w O(n2) liczby |W|,|L|,vW|Cv| można wyznaczyć LD w czasie O(D) podanym wzorem. Otrzymujemy więc rozwiązanie o złożoności czasowej O(n2+D).

Podzadanie 7

Gdy D105 oraz nie ma dodatkowego ograniczenia na n, można zastosować powyższe rozwiązanie, ale przyśpieszając wyznaczanie liczności zbiorów Cv 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ę LD,1.

Znając wartość La oraz Lb, można wyznaczyć wzór na wartość La+b. Dzięki temu można skorzystać z techniki analogicznej do szybkiego potęgowania do obliczenia LD, czyli na przykład poprzez wyznaczenie liczb L1,L2,L4,L8, i domnażając te potęgi, których bity są zapalone w D.

Alternatywnie, swoim ulubionym sposobem można wyprowadzić wzór na postać jawną rekurencji liniowej LD, otrzymując wzór LD1=|L|n2DEDn2E dla E=(vW|Cv|vL|Cv|), co można wyliczyć szybkim potęgowaniem oraz odwrotnością modulo.