https://pl.spoj.com/problems/MWP4_1E
Skrócony opis problemu:
Dla danego ciągu liczb o długości $n$, znajdź najmniejszy indeks, dla którego suma liczb za nim jest równa sumie liczb od początku do niego włącznie. Jeśli taki indeks nie istnieje - wypisz 0.
Na przykład dla $n=5$ i ciągu 4,2,3,2,1 wynik to 2 (liczymy indeksy od 1), bo dla drugiej liczby mamy: 4+2=3+2+1.
Rozwiązanie naiwne:
Zaczynając od początku ciągu możemy sumować wszystkie liczby do tej, którą bierzemy pod uwagę włącznie oraz od niej do końca i porównywać obie sumy. Jeśli będą równe, to wypisujemy indeks liczby, którą w danym momencie rozpatrujemy. Dzięki temu, że zaczynamy od początku mamy pewność, że będziemy mieli najmniejszy możliwy indeks.
Złożoność: $O(n^2)$.
Rozwiązanie sprytne:
Możemy zauważyć, że jak policzymy te 2 sumy i przesuniemy indeks na następny, i będziemy znów chcieli policzyć te sumy, to większość składników z sumach będzie taka sama. Zmieni się tylko to, że rozpatrywana przez nas liczba pójdzie nie do drugiej sumy, tylko do pierwszej - tej od początku ciągu. Możemy zatem na początku policzyć sumę wszystkich wyrazów ciągu i zapisać ją do zmiennej $suma2$, i ustawić $suma=0$. $suma2$ będzie opisywać sumę sufiksu (czyli prawej części ciągu), a $suma$ prefiksu (czyli lewej części ciągu). Gdy bierzemy pierwszy element to odejmujemy jego wartość od $suma2$ i dodajemy do $suma$, a następnie porównujemy obie sumy.
Złożoność: $O(n)$.
Ostateczny algorytm:
int main() { int n, tab[n]; // dane int i, suma = 0, suma2 = 0; get(n); for(i = 0; i < n; ++i) { get(tab[i]); suma2 += tab[i]; } for(i = 0; i < n-1; ++i) { s += tab[i]; s2 -= tab[i]; if(s == s2)break; } if(i == n-1)print(0); // jeśli doszliśmy do końca i nie udało nam się znaleźć rozwiązania else print(i+1); // bo liczymy od 0, a powinniśmy od 1 }
Brak komentarzy:
Prześlij komentarz