Perfect Number
Dzielnik właściwy liczby n to dodatni dzielnik mniejszy od samej liczby n. Liczba doskonała jest równa sumie swoich dzielników właściwych: 6 = 1 + 2 + 3. Otrzymujesz dodatnią liczbę całkowitą n. Zwróć true, jeśli n jest doskonała, a w przeciwnym razie false.
Funkcja
- ninteger
- testowana dodatnia liczba całkowita
- Zwracaboolean
- true, jeśli n jest równe sumie swoich dzielników właściwych, false w przeciwnym razie
Ograniczenia
1 ≤ n ≤ 108
Przykłady
- Wejście
- n = 28
- Wyjście
- true
- Wyjaśnienie
- Właściwe dzielniki liczby
28to1,2,4,7i14. Ich suma wynosi28, więc28jest liczbą doskonałą.
- Wejście
- n = 12
- Wyjście
- false
- Wyjaśnienie
- Właściwe dzielniki liczby
12to1,2,3,4i6. Ich suma wynosi16, czyli przekracza12.
- Wejście
- n = 1
- Wyjście
- false
- Wyjaśnienie
1nie ma żadnego właściwego dzielnika, więc suma wynosi0, a nie1.
Pytanie dodatkowe
Każda parzysta liczba doskonała ma postać 2^(p-1) × (2^p-1), gdzie 2^p-1 jest liczbą pierwszą. Czy potrafisz wypisać wszystkie liczby doskonałe mniejsze niż 10^8 za pomocą tego wzoru, bez testowania każdej liczby?
Podpowiedzi
Otwieraj je po kolei. Każda zdradza trochę więcej.
Zapisz dzielniki właściwe liczby
28. Które z nich znajdziesz, jeśli sprawdzisz tylko liczby do5?Dzielniki występują parami: jeśli
ddzielin, ton / drównież. Jeden z elementów każdej pary jest nie większy niż√n.Ustaw wartość całkowitą początkowo na
1, zwracajfalsedlan == 1i iteruj podod2, dopókid * d ≤ n. Dodawajdin / d, ale tylko raz, gdy są sobie równe.
Rozwiązanie
Definicja wymaga sumy dzielników, a oczywista pętla sprawdza każdego kandydata aż do n / 2. Dla n = 10^8 oznacza to 5 × 10^7 dzieleń. Dzielniki występują w parach, których iloczyn wynosi n, więc możesz zebrać oba elementy każdej pary, przeszukując liczby tylko do √n, czyli wykonując około 10^4 kroków.
Dodaj każdy właściwy dzielnik
Poprawne, ale nie kończy się na największych testach
Intuicja
Postępuj zgodnie z definicją. Sprawdź po kolei każdą wartość d, zaczynając od 1, a gdy n % d == 0, dodaj d do sumy bieżącej. Na końcu porównaj sumę z n. Dla 28 pętla uwzględnia 1, 2, 4, 7 i 14, a 1 + 2 + 4 + 7 + 14 = 28.
Możesz zakończyć na n / 2. Dzielnik inny niż n pozostawia iloraz wynoszący co najmniej 2, więc nigdy nie jest większy niż połowa n. To ograniczenie działa także dla n = 1: pętla wykonuje się zero razy, suma pozostaje równa 0, a odpowiedzią jest false.
Podzielenie zakresu na pół nie zmienia tempa wzrostu. Dla n = 10^8 pętla nadal wykonuje się 5 × 10^7 razy, i dzieje się tak dla każdego wejścia o takim rozmiarze, niezależnie od tego, czy jest dzielnikiem.
Algorytm
- Ustaw
totalna0. - Przejdź pętlą przez
dod1don / 2. - Jeśli
n % d == 0, dodajddototal. - Zwróć informację, czy
total == n.
def isPerfect(n):
total = 0
# No proper divisor of n is larger than n / 2.
for d in range(1, n // 2 + 1):
if n % d == 0:
total += d
return total == nZbieraj pary dzielników do pierwiastka kwadratowego
Intuicja
Gdy d dzieli n, to n / d również je dzieli. Dla 28 pary to 1 × 28, 2 × 14 i 4 × 7. W każdej parze jeden element jest nie większy niż √n, ponieważ iloczyn dwóch liczb większych od √n jest większy niż n. Wystarczy więc przeszukać liczby do √n, aby znaleźć każdą parę dokładnie raz, i dodawać oba jej elementy.
Na dwa elementy trzeba uważać. Para 1 × n zawiera samo n, które nie jest właściwym dzielnikiem: zacznij sumę od 1, a przeszukiwanie od 2. Ten początek jest nieprawidłowy dla n = 1, którego jedynym dzielnikiem jest ono samo, więc najpierw zwróć dla niego false. A gdy n jest kwadratem, pierwiastek tworzy parę z samym sobą: dla 36 para 6 × 6 powinna dodać 6 raz, a nie dwa razy.
Zapisz ograniczenie jako d * d ≤ n, dzięki czemu pozostajesz w liczbach całkowitych. Dla n = 10^8 pętla kończy się przy d = 10^4, więc wykonuje około 10^4 iteracji zamiast 5 × 10^7.
Algorytm
- Jeśli
n == 1, zwróćfalse. - Ustaw
totalna1, adna2. - Gdy
d * d ≤ n: jeślidjest dzielnikiemn, dodajd, a takżen / d, jeśli różni się odd. - Przejdź do następnej wartości
d. - Zwróć informację, czy
total == n.
def isPerfect(n):
if n == 1:
return False
total = 1 # 1 divides every n > 1; n itself does not count
d = 2
while d * d <= n:
if n % d == 0:
total += d
partner = n // d
if partner != d: # a square root pairs with itself: add it once
total += partner
d += 1
return total == n
Pułapki i przypadki brzegowe
Sztuczka z parami jest krótka, a każdy z jej błędów zmienia sumę dokładnie o jeden dzielnik.
- Liczenie samego
n. Para1 × ndodajen, przez co każda liczba wygląda tak, jakby jej suma była większa odn. Zacznij sumę od1, a wyszukiwanie od2. - Uznawanie
1za liczbę doskonałą. Gdy suma zaczyna się od1, dla wejściowej wartości1porównanie ma postać1 == 1. Suma jej właściwych dzielników wynosi0, więc obsłuż ten przypadek przed pętlą. - Dodawanie pierwiastka kwadratowego dwukrotnie. Dla
16właściwe dzielniki to1,2,4i8, a ich suma wynosi15. Dwukrotne dodanie4daje19. - Zatrzymywanie się przy
d * d < n. To pomija pierwiastek kwadratowy, więc4dla16nigdy nie zostaje uwzględnione. - Wyznaczanie granicy na podstawie pierwiastka kwadratowego w liczbie zmiennoprzecinkowej. W przypadku pojedynczej precyzji lub dla liczb większych niż
2^53w podwójnej precyzji pierwiastek z kwadratu doskonałego może być zaokrąglony w dół o jeden, przez co dzielnik zostanie pominięty. Testd * d ≤ noperuje na liczbach całkowitych i nigdy nie sprawia tego problemu.
Najczęstsze pytania3
C jaka jest złożoność czasowa sprawdzania, czy liczba jest doskonała?
Zbieranie par dzielników do √n zajmuje O(√n) czasu i O(1) pamięci. Dla n = 10^8 to około 10^4 kroków. Testowanie każdego kandydata do n / 2 ma złożoność O(n) i dla tych samych danych wejściowych wymaga około 5 × 10^7 kroków.
Ile liczb doskonałych jest mniejszych niż 10^8?
Pięć: 6, 28, 496, 8128 i 33550336. Szybko stają się coraz rzadsze. Kolejna, 8589869056, nie mieści się nawet w 32-bitowej liczbie całkowitej.
Czy istnieją nieparzyste liczby doskonałe?
Nikt nie wie. Każda dotychczas znaleziona liczba doskonała jest parzysta. Poszukiwania wykluczyły istnienie nieparzystych liczb doskonałych mniejszych niż 10^1500, ale nie ma dowodu, że nie mogą istnieć. Twoja funkcja musi działać zgodnie z definicją, a nie na podstawie przypuszczenia, że dane wejściowe są parzyste.
Podobne zadania
Zadania oparte na tych samych pomysłach. Rozwiązanie dwóch lub trzech utrwala schemat.
def isPerfect(n):
# Napisz kod tutajTest #1
Test #2
Test #3
Argument
n = 28
Oczekiwany wynik
true