Least Common Multiple
מקבלים שני מספרים שלמים חיוביים a ו-b. החזירו את הכפולה המשותפת הקטנה ביותר שלהם: המספר השלם החיובי הקטן ביותר שגם a וגם b מתחלקים בו ללא שארית.
פונקציה
- ainteger
- המספר השלם החיובי הראשון
- binteger
- המספר השלם החיובי השני
- מחזירהinteger
- המספר השלם החיובי הקטן ביותר שהוא כפולה של גם a וגם b
אילוצים
1 ≤ a ≤ 1061 ≤ b ≤ 106- התשובה נכנסת במספר שלם חתום בן 32 סיביות:
lcm(a, b) ≤ 231-1. המכפלהa × bעשויה שלא להיכנס.
דוגמאות
- קלט
- a = 4b = 6
- פלט
- 12
- הסבר
- הכפולות של
6מתחילות ב־6, 12, 18; הכפולות של4מתחילות ב־4, 8, 12. המספר הראשון שמופיע בשתי הרשימות הוא12.
- קלט
- a = 7b = 3
- פלט
- 21
- הסבר
- ל־
7ול־3אין גורם משותף מלבד1, ולכן הכפולה המשותפת הקטנה ביותר שלהם היא המכפלה שלהם,21.
- קלט
- a = 15b = 45
- פלט
- 45
- הסבר
15מחלק את45ללא שארית, לכן45הוא כבר כפולה משותפת של שניהם, ולא קיימת כפולה קטנה יותר של45.
שאלת המשך
האם תוכל למצוא את המחלק המשותף הגדול ביותר בלי להשתמש כלל בחילוק או בשארית, אלא רק בחיסור ובחלוקה לשניים?
רמזים
פתחו אותם אחד אחד. כל רמז חושף קצת יותר.
התשובה היא כפולה של המספר הגדול יותר. האם צריך לנסות כל מספר שביניהם, או רק את הכפולות של המספר הגדול יותר?
המחלק המשותף הגדול ביותר והכפולה המשותפת הקטנה ביותר קשורים זה לזה:
gcd(a, b) × lcm(a, b) = a × b. האלגוריתם של אוקלידס מוצא את המחלק המשותף הגדול ביותר בכמה עשרות צעדים.חשבו את המחלק המשותף הגדול ביותר, ואז החזירו
a / gcd × b. חלקו קודם: המכפלהa × bעלולה לחרוג מטווח של מספר שלם בן 32 ביט, גם כשהתשובה מתאימה לטווח.
פתרון
הכפולה המשותפת הקטנה ביותר והמחלק המשותף הגדול ביותר קשורים בעובדה אחת: gcd(a, b) × lcm(a, b) = a × b. לכן התשובה המהירה היא a × b / gcd(a, b). המכפלה יכולה להגיע ל־10^12 ולגלוש ממספר שלם בן 32 סיביות, גם כשהתשובה נכנסת בטווח, ולכן יש לחלק במחלק המשותף הגדול ביותר לפני הכפל.
סופרים מהמספר הגדול יותר
נכונה, אבל לא מסתיימת בבדיקות הגדולות ביותר
האינטואיציה
התשובה היא לפחות המספר הגדול יותר. אתחל את m ל־max(a, b) והוסף 1 עד ששני המספרים מחלקים אותו; אתה מנסה מועמדים בסדר עולה, ולכן הפגיעה הראשונה היא הקטנה ביותר. עבור 4 ו־6 מנסים מ־6 עד 11 ועוצרים ב־12. הלולאה תמיד מסתיימת, כי a × b הוא כפולה משותפת.
מספר הניסיונות הוא בערך בגודל התשובה. עבור המספרים הראשוניים 46337 ו־46327 התשובה היא 2146654199, יותר משני מיליארד ניסיונות.
אלגוריתם
- הגדר את
mלערך הגדול יותר מביןaו־b. - כל עוד
m % aאוm % bאינם0, הוסף 1 ל־m. - החזר את
m.
def lcm(a, b):
m = max(a, b)
while m % a != 0 or m % b != 0:
m += 1
return mעבור בקפיצות של כפולות המספר הגדול יותר
האינטואיציה
התשובה חייבת להיות כפולה של המספר הגדול יותר, big, לכן דלגו בקפיצות של big, 2 × big, 3 × big ועצרו בראשון שהמספר הקטן יותר מתחלק בו. עבור 4 ו-6 מנסים את 6, ואז את 12.
מכיוון ש-small × big הוא תמיד כפולה משותפת, הלולאה רצה לכל היותר min(a, b) פעמים, לכל היותר מיליון כאן. זה מהיר מספיק עבור המגבלות האלה, אבל מספר האיטרציות עדיין גדל עם הקלט; עבור מספרים עד 10^18 זה כבר לא היה מספיק מהיר.
אלגוריתם
- נסמן את המספר הגדול יותר ב-
bigואת המספר הקטן יותר ב-small. - נגדיר
m = big. - כל עוד
m % smallאינו0, נוסיף אתbigל-m. - נחזיר את
m.
def lcm(a, b):
big, small = max(a, b), min(a, b)
m = big
while m % small != 0:
m += big
return mחלקו ב־gcd, ואז הכפילו
האינטואיציה
פרק את שני המספרים לגורמים ראשוניים. עבור כל מספר ראשוני, ה־gcd לוקח את החזקה הקטנה יותר מבין השתיים שלו, וה־lcm את הגדולה יותר, כך שביחד הם משתמשים בכל גורם של a ושל b בדיוק פעם אחת: gcd × lcm = a × b. עבור 4 = 2² ו־6 = 2 × 3, ה־gcd הוא 2 וה־lcm הוא 2² × 3 = 12.
האלגוריתם של אוקלידס מוצא את ה־gcd ב־O(log(min(a, b))) צעדים. לאחר מכן חשב את a / gcd × b בסדר הזה: ה־gcd מחלק את a ללא שארית, כך ששום דבר לא הולך לאיבוד, ואף שלב אינו עולה על התוצאה. a × b / gcd גורם לגלישה במספר שלם של 32 סיביות כאשר a = b = 10^6, שבו המכפלה היא 10^12 והתוצאה היא רק 10^6.
אלגוריתם
- העתק את
aואתbאלxואלy. - כל עוד
yאינו0, החלף את(x, y)ב-(y, x % y). כעתxהוא ה-gcd. - חלק את
aב-x. - כפול את התוצאה ב-
bוהחזר אותה.
def lcm(a, b):
x, y = a, b
while y != 0:
x, y = y, x % y
# x is gcd(a, b). Divide before multiplying.
return a // x * b
מלכודות ומקרי קצה
- חישוב
a × bתחילה. ב-Java, ב-C, ב-C++, ב-C# וב-Rust, המכפלה של שני מספרים הקרובים ל-10^6חורגת מטווח של מספר שלם בן 32 סיביות ומתקבלת שגויה או שלילית (ב-build לניפוי שגיאות של Rust מתרחשת קריסה), אף שה-LCM נכנס לטווח. - חלוקה בנקודה צפה. התוצאה עלולה להתקבל בתור
2.146654199E9או לאבד את הספרות האחרונות שלה; יש להשאיר הכול במספרים שלמים. - הרצת לולאת אוקלידס על
aועלbעצמם. לאחר מכן הם מכילים את ה-GCD ואת0, לכן יש לעבוד על עותקים. - הנחה שהתשובה היא
a × b. זה נכון רק כשהמספרים אינם חולקים גורם משותף:lcm(4, 6)הוא12, ולא24.
שאלות נפוצות3
מהי הנוסחה למציאת הכפולה המשותפת הקטנה ביותר של שני מספרים?
lcm(a, b) = a × b / gcd(a, b), מחושב כך: a / gcd(a, b) × b, כדי שאף ערך ביניים לא יעלה על התוצאה. עבור 4 ו־6, ה־gcd הוא 2, ו־4 / 2 × 6 = 12.
מהי סיבוכיות הזמן של חישוב ה־LCM?
בעזרת נוסחת ה־gcd, זמן הריצה הוא O(log(min(a, b))), כמו עלות האלגוריתם של אוקלידס, וצריכת הזיכרון היא O(1). מעבר על כפולות של המספר הגדול יותר הוא O(min(a, b)), וספירה באחד היא O(lcm(a, b)).
איך מוצאים את הכפולה המשותפת הקטנה ביותר של יותר משני מספרים?
קפלו את הרשימה: lcm(a, b, c) = lcm(lcm(a, b), c). עבור [4, 6, 10], מתקיים lcm(4, 6) = 12 וגם lcm(12, 10) = 60. הערך המצטבר גדל במהירות, לכן השתמשו במספרים שלמים בני 64 סיביות כשהרשימה ארוכה.
בעיות דומות
בעיות שמשתמשות באותם רעיונות. פתרון של שתיים או שלוש מהן מקבע את הדפוס.
def lcm(a, b):
# כתבו כאן את הקודבדיקה #1
בדיקה #2
בדיקה #3
ארגומנטים
a = 4 b = 6
הפלט הצפוי
12