小明开了一家糖果店。
他别出心裁:把水果糖包成4颗一包和7颗一包的两种。
糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。
当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。
大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数 n,mn,m,表示每种包装中糖的颗数。
输出格式
一个正整数,表示最大不能买到的糖数。
数据范围
2≤n,m≤10002≤n,m≤1000,
保证数据一定有解。
输入样例:
4 7
输出样例:
17
一、代码解析
1、解法一
- 保证数据一定有解,两个数字必须互质,可以保证有解且解的数目无穷
- 利用最大公倍数,m和n无论怎么组合都必定会得到最大公倍数,即可推出 a * x +b *y的上界是m * n
m,n = map(int,input().split())
set1 = set() #建立空集合
for x in range(n): #n是表示当x为n时,y为0,可以得到x*n = m*n,即他的最小公倍数(可看为边缘)
for y in range(m): # 同理y = m时,x为0时,也是可看为边缘
if m * x + y * n <= m * n:
set1.add(m * x + y * n) #每一个可用n,m组合得到的数放入集合中
i = m * n - 1 #因为上面m和n为循环右开,即add到集合中没有m*n
while i > 0: #从后面数回来,可率先找到最大的
if not i in set1: #查找i是否在集合中,即找到最大不在集合中的数
break #循环结束
i -= 1
print(i) #将第一个找到不在集合中的最大数打印,即买不到的数
2、解法二
(虽然我也不太清楚欧几里得
m,n = map(int,input().split())
print(m*n-(m+n)) #利用数论,欧几里得定理
二、需要注意的细节
1、区分空集合 和 字典
- 建立空集合是set(),集合里有存放数据才是{2,4,5}
- 建立字典是{},字典里存放数据是键值对
2、字典查找比列表count查找的可取之处
- (最快)字典查找是 num in set (num是否在字典里)
- (快)列表查找是 num in li (num是否在列表li里)
- (超时)列表查找 li.count(num) == 0 (num在列表的数目为0)
参考:
https://blog.csdn.net/weixin_39969953/article/details/110771742
3、 补充一下集合set的使用
- set是无序的,没有下标
- 增 :set.add(x)
- 删 : set.pop() 随机删除一个元素
- 改:改不了无序的
- 查: num in set
- 且在集合中没有重复的元素