Perfect Number
מחלק ראוי של n הוא מחלק חיובי שקטן מ־n עצמו. מספר מושלם שווה לסכום המחלקים הראויים שלו: 6 = 1 + 2 + 3. נתון לך מספר שלם חיובי n. החזר true אם n מושלם, ו־false אחרת.
פונקציה
- ninteger
- המספר השלם החיובי לבדיקה
- מחזירהboolean
- true אם n שווה לסכום המחלקים האמיתיים שלו, אחרת false
אילוצים
1 ≤ n ≤ 108
דוגמאות
- קלט
- n = 28
- פלט
- true
- הסבר
- המחלקים הראויים של
28הם1,2,4,7ו־14. סכומם הוא28, ולכן28הוא מספר מושלם.
- קלט
- n = 12
- פלט
- false
- הסבר
- המחלקים האמיתיים של
12הם1,2,3,4ו-6. סכומם הוא16, שעולה על12.
- קלט
- n = 1
- פלט
- false
- הסבר
- ל־
1אין כלל מחלקים ראויים, לכן הסכום הוא0, ולא1.
+16 בדיקות נסתרות בשליחה
שאלת המשך
לכל מספר מושלם זוגי יש את הצורה 2^(p-1) × (2^p-1) כאשר 2^p-1 הוא ראשוני. האם תוכל לרשום את כל המספרים המושלמים הקטנים מ־10^8 באמצעות הנוסחה הזאת, בלי לבדוק כל מספר?
רמזים
פתחו אותם אחד אחד. כל רמז חושף קצת יותר.
כתבו את המחלקים האמיתיים של
28. אילו מהם הייתם מוצאים אילו הסתכלתם רק על מספרים עד5?מחלקים מופיעים בזוגות: אם
dמחלק אתn, גםn / dמחלק אותו. אחד האיברים בכל זוג קטן או שווה ל־√n.התחילו את הסכום ב־
1, החזירוfalseעבורn == 1, והריצו לולאה עלdהחל מ־2כל עודd * d ≤ n. הוסיפו אתdואתn / d, אך רק פעם אחת כשהם שווים.
פתרון
ההגדרה מבקשת סכום של מחלקים, והלולאה המתבקשת בודקת כל מועמד עד n / 2. עבור n = 10^8 מדובר ב־5 × 10^7 פעולות חילוק. מחלקים מופיעים בזוגות שמכפלתם היא n, כך שאפשר לאסוף את שני האיברים בכל זוג ובמקביל לחפש רק עד √n, בערך 10^4 צעדים.
חבר כל מחלק אמיתי
נכונה, אבל לא מסתיימת בבדיקות הגדולות ביותר
האינטואיציה
פעלו לפי ההגדרה. בדקו כל d החל מ־1 כלפי מעלה, וכאשר n % d == 0, הוסיפו את d לסכום מצטבר. בסוף השוו את הסכום ל־n. עבור 28, הלולאה אוספת את 1, 2, 4, 7 ואת 14, ו־1 + 2 + 4 + 7 + 14 = 28.
אפשר לעצור ב־n / 2. מחלק שאינו n משאיר מנה של לפחות 2, ולכן הוא לעולם אינו גדול ממחצית n. הגבול מתאים גם ל־n = 1: הלולאה רצה אפס פעמים, הסכום נשאר 0, והתשובה היא false.
חלוקת הטווח לשניים אינה משנה את קצב הגידול. עבור n = 10^8, הלולאה עדיין רצה 5 × 10^7 פעמים, והיא עושה זאת עבור כל קלט בגודל הזה, בין אם הוא מחלק ובין אם לא.
אלגוריתם
- הגדר את
totalל־0. - עבור עם
dמ־1עדn / 2. - אם
n % d == 0, הוסף אתdל־total. - החזר האם
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 == nאיסוף זוגות מחלקים עד השורש הריבועי
האינטואיציה
כש־d מחלק את n, גם n / d מחלק אותו. עבור 28 הזוגות הם 1 × 28, 2 × 14 ו־4 × 7. בכל זוג אחד מהאיברים קטן או שווה ל־√n, כי מכפלה של שני מספרים שגדולים מ־√n גדולה מ־n. לכן חיפוש עד √n מוצא כל זוג פעם אחת, ומוסיפים את שני האיברים תוך כדי החיפוש.
יש שני איברים שדורשים תשומת לב. הזוג 1 × n כולל את n עצמו, שאינו מחלק אמיתי: מתחילים את הסכום ב־1 ואת החיפוש ב־2. נקודת התחלה זו שגויה עבור n = 1, שהמחלק היחיד שלו הוא עצמו, ולכן מחזירים עבורו תחילה false. וכאשר n הוא ריבוע, השורש מופיע בזוג עם עצמו: עבור 36, צריך להוסיף את 6 פעם אחת ולא פעמיים.
כותבים את הגבול כך: d * d ≤ n, וכך נשארים במספרים שלמים. עבור n = 10^8 הלולאה נעצרת ב־d = 10^4, ולכן היא רצה בערך 10^4 פעמים במקום 5 × 10^7.
אלגוריתם
- אם
n == 1, יש להחזירfalse. - יש להגדיר את
totalכ-1ואתdכ-2. - כל עוד
d * d ≤ n: אםdמחלק אתn, יש להוסיף אתd, ולהוסיף גם אתn / dכאשר הוא שונה מ-d. - יש לעבור ל-
dהבא. - יש להחזיר האם
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
מלכודות ומקרי קצה
שיטת הזוגות קצרה, וכל אחת מהשגיאות שלה משנה את הסכום בדיוק במחלק אחד.
- סופרים גם את
nעצמו. הזוג1 × nמוסיף אתn, ואז נראה שלכל מספר יש סכום גדול מ-n. מתחילים את הסכום ב-1ואת החיפוש ב-2. - קובעים ש-
1הוא מספר מושלם. כשהסכום מתחיל ב-1, עבור הקלט1מתקבלת ההשוואה1 == 1. סכום המחלקים האמיתיים שלו הוא0, לכן צריך לטפל בו לפני הלולאה. - מוסיפים את השורש הריבועי פעמיים. עבור
16, המחלקים האמיתיים הם1,2,4ו-8, וסכומם15. הוספת4פעמיים נותנת19. - עוצרים בתנאי
d * d < n. כך מדלגים על השורש הריבועי כולו, ולכן4של16לעולם לא נספר. - קובעים את הגבול לפי שורש ריבועי בנקודה צפה. בדיוק יחיד, או מעל
2^53בדיוק כפול, תוצאת השורש של ריבוע מושלם עלולה להיות קטנה באחד ולגרום להשמטת מחלק. הבדיקהd * d ≤ nנשארת במספרים שלמים, ולכן הבעיה הזאת לעולם לא מתרחשת.
שאלות נפוצות4
מהי סיבוכיות הזמן של בדיקת מספר מושלם?
איסוף זוגות מחלקים עד √n דורש זמן של O(√n) ומקום של O(1). עבור n = 10^8, מדובר בכ־10^4 צעדים. בדיקת כל מועמד עד n / 2 דורשת זמן של O(n), כלומר כ־5 × 10^7 צעדים עבור אותו קלט.
כמה מספרים מושלמים יש מתחת ל־10^8?
חמישה: 6, 28, 496, 8128 ו־33550336. הם נעשים נדירים במהירות. הבא בתור, 8589869056, אפילו לא נכנס למספר שלם בן 32 סיביות.
האם קיימים מספרים מושלמים אי־זוגיים?
איש אינו יודע. כל מספר מושלם שנמצא עד כה הוא זוגי. חיפושים שללו מספרים מושלמים אי-זוגיים הקטנים מ־10^1500, אבל אין הוכחה שהם לא יכולים להתקיים. הפונקציה שלך צריכה לפעול לפי ההגדרה, ולא על סמך ניחוש שהקלט זוגי.
מה ההבדל בין מספרים מושלמים, שופעים וחסרים?
השוו את סכום המחלקים האמיתיים למספר. אם הם שווים, המספר מושלם, כמו 28. אם הסכום גדול יותר, המספר שופע, כמו 12, שסכום המחלקים שלו הוא 16. אם הסכום קטן יותר, המספר חסר, כמו כל מספר ראשוני, שהמחלק האמיתי היחיד שלו הוא 1.
בעיות דומות
בעיות שמשתמשות באותם רעיונות. פתרון של שתיים או שלוש מהן מקבע את הדפוס.
Python
def isPerfect(n):
# כתבו כאן קודמקרה 1
מקרה 2
מקרה 3
קלט
n = 28
צפוי
true