题目:
Problem B. 最小公倍数
时间限制 1000 ms
内存限制 128 MB
题目描述
给出两个正整数a,b(1< =a,b< =10^100),求这两个数的最小公倍数。

输入数据:
仅一行,包含两个正整数a和b, 中间以一个空格隔开
输出数据:
仅包含一行,为a和b的最小公倍数lcm(a,b)

样例输入

123 321


样例输出

13161

这个题目本身的思想并不难。可以根据lcm(a, b) = a*b / gcd(a, b)快速得到结果。gcd即最大公约数,可以用欧几里得算法求得。

这个题目的难点在于,数据范围是10^100次方,远超了C/C++语言int、long long等各种数据类型的最大长度。而大家在完成算法题的时候一般习惯(老师推荐)使用C/C++完成。因此,若用C语言写,就要自己写一遍高精度。而高精度的除法、取模的书写又很折磨人,因此这个题大家一般采用Python/Java来完成,因为Python中数的长度不受int32/int64的限制,而Java有现成的BigInteger可用。

这道题我选择使用Python来完成。我的代码是这样的

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a%b)

str = input()
a = int(str.split(" ")[0])
b = int(str.split(" ")[1])
g = gcd(a, b)
print(int(a*b/g))

然而,这份代码WA(Wrong Answer)了。平台善良的告诉我挂掉的数据点是:

123456789 987654321

这个数很大,难以手动计算。于是,我自然而然的想到了对拍(用另一种不管时空复杂度的方法实现这道算法题,用来验证代码是否在某些数据点的输入下有正确的输出)。同时,我非常的懒,于是我直接在网上找了一个最小公倍数计算器,发现我的代码和对拍结果一致。

于是,我开始凌乱了,开始了瞎试,损失了一堆WA的penalty(罚时)。最后,发现,是Python的精度问题。最后的AC代码是

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a%b)

str = input()
a = int(str.split(" ")[0])
b = int(str.split(" ")[1])
g = gcd(a, b)
print(a*b//g)

由于精度问题,int(a*b/g)中a*b/g会比正确结果少约0.001,之后int再向下取整,导致了输出结果比正确结果少了1。

最后由于大量的penalty,我这次作业的Rank非常难看。之前从未注意到过Python的大整数精度问题,这次也算是长教训了。