「网易官方」极客战记(codecombat)攻略-沙漠-最大公约数-tiresome-gcd

(点击图片进入关卡)

并非所有算法都是相同的。

简介

两个或多个非全为零的整数的最大公约数( 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)
 
本攻略发于极客战记官方教学栏目,原文地址为:
原文地址:https://www.cnblogs.com/codecombat/p/13328083.html