Informatyczny kącik olimpijski
Egzamin
Tym razem omówimy zadanie Egzamin, które pojawiło się w 2010 roku na Junior Balkan Olympiad in Informatics w Szumen (Bułgaria).
Zadanie. Egzamin: Dany jest ciąg złożony z liczb naturalnych, oraz liczba Ile jest podciągów ciągu których suma elementów wynosi przynajmniej Dla przykładu, ma podciągów, które mają sumę przynajmniej Są to podciągi: oraz
Rozwiązanie
Pomysł, który jako pierwszy nasuwa się na myśl, polega na obliczeniu sumy każdego podciągu, a następnie zliczeniu tych sum, których wartość jest nie mniejsza niż
Zastanówmy się teraz, jaka jest złożoność opisanego rozwiązania. Ciąg ma podciągów długości podciągów długości wreszcie podciągów długości Zatem, suma długości wszystkich podciągów wynosi: Powyższą sumę można zinterpretować nieco inaczej: każdy z elementów ciągu należy do podciągów (dla ustalonego elementu pozostałych elementów tworzy podciągów). Zatem liczba składników we wszystkich sumach wynosi co daje nam złożoność czasową
Rozwiązanie
Spróbujmy przyspieszyć powyższe rozwiązanie. Będziemy obliczali sumy podciągów w kolejności niemalejących długości (najpierw podciągi długości jeden, potem długości dwa, trzy, itd.). Załóżmy, że obliczamy sumę podciągu (podciąg ma długość indeksy kolejnych elementów tworzą ciąg ). Suma elementów tego ciągu to suma podciągu (którą obliczyliśmy wcześniej, ponieważ przeglądamy podciągi od najkrótszych do najdłuższych) powiększona o W tym podejściu obliczenie sumy każdego z podciągów odbywa się w czasie stałym, co daje nam złożoność czasową
Rozwiązanie
W tym rozwiązaniu skorzystamy z techniki Meet in the middle.
Podzielmy ciąg na dwa ciągi równej długości (jeśli długość ciągu jest nieparzysta, wtedy niech pierwszy ciąg zawiera o jeden element więcej): lewy oraz prawy Następnie, dla każdego z nich, obliczmy sumy podciągów. Możemy to zrobić w czasie korzystając z algorytmu opisanego w poprzedniej sekcji. Niech oznacza sumy podciągów i niech oznacza sumy podciągów
Zauważmy teraz, że dowolny podciąg ciągu spełnia jeden z trzech poniższych warunków:
Warunek (I): wszystkie elementy należą do
Aby obliczyć liczbę podciągów o sumie przynajmniej których wszystkie elementy należą do wystarczy zliczyć te elementy ciągu które mają wartość przynajmniej Formalnie jest to moc zbioru: Sprawdzenie tego warunku odbywa się w czasie liniowym od liczby podciągów czyli
Warunek (II): wszystkie elementy należą do
Analogicznie jak warunek (I).
Warunek (III): część elementów należy do część należy do
W tym przypadku chcemy obliczyć liczbę takich par dla oraz że Ten problem rozbijemy na podproblemów. Dla każdego obliczymy, ile jest takich że
W tym celu posortujmy ciąg i otrzymany ciąg nazwijmy Załóżmy, że obliczamy wynik dla ustalonego Za pomocą wyszukiwania binarnego szukamy takiego najmniejszego że Jeśli takie istnieje, wtedy dla każdego zachodzi ponieważ jest niemalejący. Stąd, należy do par, które mają sumę przynajmniej Jeśli zaś takie nie istnieje, to nie tworzy żadnej pary o sumie przynajmniej
Faza sortowania zajmuje czas Wyznaczenie liczby poprawnych par, dla ustalonej wartości, za pomocą wyszukiwania binarnego zajmuje czas Wszystkich wartości do sprawdzenia jest ( jest rzędu ), co daje całkowitą złożoność
Przykład. Prześledźmy opisany algorytm na przykładzie ciągu w którym szukamy liczby podciągów o sumie przynajmniej Najpierw dzielimy ciąg na dwa ciągi i dla każdego z nich obliczamy sumy wszystkich jego podciągów:
Z warunku (I) mamy podciąg, z warunku (II) również Przechodzimy do warunku (III). Najpierw sortujemy otrzymując Teraz wyznaczamy wyniki dla kolejnych elementów : Ostatecznym wynikiem jest: