- 作业题目
- 1、求N个数的最大公约数和最小公倍数。
- 2、Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:
1、 x和a0的最大公约数是a1;
2、 x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。
输入格式
输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
输出格式
输出共n行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
- 算法思路
- 求N个数的最大公约数和最小公倍数
对于输入的任意一组数
1)、选取本组数中的最小数a
2)、构成范围(1,a)
3)、输入数字的每一个数字,依次秋与(1,a)范围内的每一个数,在(1,a)中,将余数为“0”的数字筛选出构成一组数,组名为b。
4)、统计b组中的每一个出现过的数字的出现的次数,次数与输入的数字的个数相同者筛选出,即为n个数的公约数。
5)、求最大值,即为n个数的最大公约数。
6)、对最初输入的数,逐一与最大公约数相除,将所有商与做大公约数相乘,即为n个数的最小公倍数。
2、Hankson问题
1)、构造求两个数的最小公倍数函数和求两个数的最大公约数函数
2)、对于范围(0, b1),将此范围内的数逐一与a0求最大公约数,将最大公约数与a1相等的数筛选出来构成一组,组名为divisor_class。
3)、对于范围(0, b1),将此范围内的数逐一与b0求最小公倍数,将最小公倍数与b1相等的数筛选出来构成一组,组名为multiple_class。
4)、统计两组数中相等数的个数,即为x值。
程序源代码 """ @文件:求n个数的最大公约数和最小公倍数 @说明:求n个数的最大公约数和最小公倍数,并解决Hankson问题 @作者:王佳磊 @时间:2019.3.22 """ # 键入一组数(4位) def Input_(): a0 = int(input()) a1 = int(input()) b0 = int(input()) b1 = int(input()) return a0, a1, b0, b1 # 两个数最大公约数求解(辗转相除法的嵌套调用) def divisor(a,b): if a < b: # 通过比较求两个数中的最大值和最小值 temp = a a = b b = temp while b != 0: # 通过循环求两数的余数,直到余数为0 temp = a % b a = b b = temp return a # 返回最大公约数到调用函数处 # 两个数最小公倍数求解 def multiple(a,b): temp = divisor(a, b) return a*b/temp # x求解 def cacular_x(a0,a1,b0,b1): multiple_class = [] # (0,b1)范围内与b0的最小公倍数等于b1的一组数 divisor_class = [] # (0,b1)范围内与a0的最大公约数等于a1的一组数 flag = 0 for y in range(0, b1 + 1): # 求(0,b1)范围内与b0的最小公倍数等于b1的数 if multiple(b0, y) == b1: multiple_class.append(y) for z in range(0, b1 + 1): # 求(0,b1)范围内与a0的最大公约数等于a1的数 if divisor(a0, z) == a1: divisor_class.append(z) for p in range(0, len(multiple_class)): # 寻找divisor_class中与multiple_class中相等的数 for q in range(0, len(divisor_class)): if multiple_class[p] == divisor_class[q]: flag = flag + 1 # 满足Hankson问题条件的个数 print("x的值为%d" % flag) if __name__ == "__main__": print("Hankson问题") a = input("请输入数据组数:") for x in range(0, int(a)): print("请输入第%d组数据:" % (x+1)) a0, a1, b0, b1 = Input_() while a0 % a1 != 0 or b1 % b0 != 0: print("输入错误,请重新输入!") a0, a1, b0, b1 = Input_() cacular_x(a1, a1, b0, b1) print("求n个数的最大公约数") a = [] flag = 0 print("结束输入请输入0,请输入一组数:") while flag == 0: number = int(input()) a.append(number) if number == 0: flag = flag + 1 a.remove(0) # 删除标记带来的0 divisor_number = [] # 所有数的约数列表 mon_number = [] # 所有数的公约数列表 min_number = min(a) # 范围(a中最小的数) for s in range(0, len(a)): for t in range(1, min_number+1): remainder = a[s] % t if remainder == 0: divisor_number.append(t) for w in range(1, min_number+1): if divisor_number.count(w) == len(a): mon_number.append(w) # n个数的最大公约数max_mon_number max_mon_number = max(mon_number) print("最大公约数为:%d" % max_mon_number) waitfor_number = [] #待相乘数列表 for v in range(0, len(a)): h = a[v]/max_mon_number waitfor_number.append(h) # n个数的最小公倍数min_mon_number min_mon_number = 1 for j in range(0, len(waitfor_number)): min_mon_number = min_mon_number * waitfor_number[j] min_mon_number = int(min_mon_number * max_mon_number) print("最小公倍数为:%d" % min_mon_number)
三、流程图
求n个数的最大公约数和最小公倍数
Hankson问题
四、调试、测试及运行结果
调试
hankson求解x
输入了一组数:41 1 96 288开始进行遍历,遍历(0,b1)范围内
遍历divisor_class和multiple_class两组数,根据本文的设计思路,寻找符合条件的x的个数
根据q的显示,此时已遍历至divisor_class组中第20个
此时已遍历至multiple_class组中的第二个数,准备在divisor_class组中寻找与其相同的数
求n个数的最大公约数和最小公倍数
输入一组数:6 12 18 24 36 ,输入0表示结束输入(不包括0)
测试及运行结果
Hankson问题
测试两组数
第一组测试数为:41 1 96 288 运行结果:x值为6(满足条件的数有6个)
输入数字条件错误测试,41不为2的倍数
第二组测试数:95 1 37 1776 运行结果:x值为2(满足条件的数有两个)
求n个数的最大公约数和最小公倍数
测试数字:6 12 18 24 36
测试结果:最大公约数:6
最小公倍数:864
- 总结
本文提出了一种求n个数的最大公约数和最小公倍数的方法
对于输入的任意一组数
1)、选取本组数中的最小数a
2)、构成范围(1,a)
3)、输入数字的每一个数字,依次秋与(1,a)范围内的每一个数,在(1,a)中,将余数为“0”的数字筛选出构成一组数,组名为b。
4)、统计b组中的每一个出现过的数字的出现的次数,次数与输入的数字的个数相同者筛选出,即为n个数的公约数。
5)、求最大值,即为n个数的最大公约数。
6)、对最初输入的数,逐一与最大公约数相除,将所有商与做大公约数相乘,即为n个数的最小公倍数。
即先求出n个数的所有公约数,再求出其最大值即为最大公约数,最后对输入的数逐一除以最大公约数,将所有的商和最大公约数相乘,积即为最小公倍数。
但是,在解决Hankson问题是并未应用到以上算法,而是利用辗转相除法求两个数的最大公约数和最小公倍数的方法来解决Hankson问题。