(点击图片进入关卡)
并非所有算法都是相同的。
简介
两个或多个非全为零的整数的最大公约数( gcd ),指的是除这些整数能除尽的最大正整数。
要进入宝库,你需要说出密码。我们的情报员获得了密码相关的两个数字密匙。 要确定密码,你需要求出这两个数字的最大公约数。
要求出最大公约数,从大到小枚举小于给定数字的所有可能数字,是最简单的方法(但较慢)。 如果两个数字都能被当前数字整除,没有余数,那它就是最大公约数了。
或许,还有别的方法?
默认代码
# 计算秘密数字并进入财政部。
# 这两个人知道密码的关键。
friends = hero.findFriends()
number1 = friends[0].secretNumber
number2 = friends[1].secretNumber
# 只是为了确保第一个数字更大。
if number2 > number1:
swap = number1
number1 = number2
number2 = swap
# 这是简单但慢的功能找到gcd。
def bruteforceGCD (a, b):
hero.say("朴素的算法。")
cycles = 0
# 我们列举了所有可能的除数。
counter = b
while True:
cycles += 1
if cycles > 100:
hero.say("计算是困难的。我累了。")
break
# 如果两个数字都有 "counter" 除数。
if a % counter == 0 and b % counter == 0:
break
counter -= 1
hero.say("我使用了 " + cycles + " 周期")
return counter
# 这是找到gcd的聪明方式。
def euclidianGCD (a, b):
cycles = 0
while b:
cycles += 1
swap = b
b = a % b
a = swap
hero.say("我使用了 " + cycles + " 周期")
return a
# 也许你需要使用另一个功能?
secretNumber = bruteforceGCD(number1, number2) # ∆
hero.moveXY(48, 34)
hero.say(secretNumber)
# 财政部是开放的(我希望如此)!去那儿!
hero.moveXY(68, 34)
概览
求最大公约数 gcd 的朴素算法可以称作蛮力算法,因为它需要蛮力枚举所有可能的答案。 如果有两个数字 A 和 B ( A > B ),那我们就从 B 开始,逐次减一。 这就需要从 B 算到 1 ,总共 B 个周期。对于当前的关卡,这会是 10 ** 15 周期。
数字很小时这还没关系,但如果数字很大(例如:2**100),且我们需要求出多组数字的最大公约数(密码学中经常要用到这些),情况会如何呢? 就算是最强的计算机,也会碰到麻烦。更何况,能找到更优解决方案的时候,我们不希望浪费宝贵的计算资源。
在默认代码中,你可以看到函数 euclidianGCD 。它所实现的是欧几里得算法,能更快速地求出最大公约数。 欧几里得算法基于的原理是,在将大数替换为它与小数之间的差值后,两个数的最大公约数会保持不变。 现在你并不需要理解算法本身。这里我们主要要讲的是,求解同一个问题通常会有多种算法,不同算法效率也会不同。
P.S.: 如果你想了解欧几里得算法的详细内容,请参阅维基百科页面Wikipedia
最大公约数 解法
# 计算秘密数字并进入财政部。
# 这两个人知道密码的关键。
friends = hero.findFriends()
number1 = friends[0].secretNumber
number2 = friends[1].secretNumber
# 只是为了确保第一个数字更大。
if number2 > number1:
swap = number1
number1 = number2
number2 = swap
# 这是简单但慢的功能找到gcd。
def bruteforceGCD (a, b):
hero.say("朴素的算法。")
cycles = 0
# 我们列举了所有可能的除数。
counter = b
while True:
cycles += 1
if cycles > 100:
hero.say("计算是困难的。我累了。")
break
# 如果两个数字都有 "counter" 除数。
if a % counter == 0 and b % counter == 0:
break
counter -= 1
hero.say("我使用了 " + cycles + " 周期")
return counter
# 这是找到gcd的聪明方式。
def euclidianGCD (a, b):
cycles = 0
while b:
cycles += 1
swap = b
b = a % b
a = swap
hero.say("我使用了 " + cycles + " 周期")
return a
# 也许你需要使用另一个功能?
secretNumber = bruteforceGCD(number1, number2) # ∆
hero.moveXY(48, 34)
hero.say(secretNumber)
# 财政部是开放的(我希望如此)!去那儿!
hero.moveXY(68, 34)
本攻略发于极客战记官方教学栏目,原文地址为: