已知两个1~n之间的不同的数,甲知道两数之和,乙知道两数之积。
甲问乙:“你知道是哪两个数吗?”乙说:“不知道”;
乙问甲:“你知道是哪两个数吗?”甲说:“也不知道”;
于是,乙说:“那我知道了”;
随后甲也说:“那我也知道了”;
这两个数是多少?
思路很暴力,把所有的组合先列出来,两个数且不相同共有29+28+27+...1种可能性也就是435种
然后用字典将结果装起来:a,b为两个数,名称就是元组形式的(a,b),内容为两者之和和两者之积
dic={(a,b):(a+b,a*b) for a in range(1,n+1) for b in range(a+1,n+1)}
#先列出所以可能
#dic的单位是key:(a,b) value:(a+b,a*b)
甲和乙的对话,建模后可以直接理解为:已知两数之积/和,两数只有单解(对应甲乙说:“那我知道了”)或一定有多解(对应甲乙说:“我不知道”)
而只需要将不符合题意的组合删除,就能得到最终的解。
并定义一个函数,专门用来删除不符合题意的解
def pop(dic,is_product,is_single):
#用来剔除多解或单解
#参数二:是积还是和
#参数三:是单解还是多解
lis,lis2=list(zip(*dic.values()))[is_product],[]
for j in lis:
if (lis.count(j) == 1)==is_single:lis2.append(j)
#如果总数为1,及没有多解
#如果总是不为1,及有多解
#然后把不符条件的放入lis2,准备删除
dic={k:v for k,v in dic.items() if v[is_product] in lis2}
#删除多解或删除单解
return dic
分析题目:
#乙不知道是哪两个数,也就是有多解
#如果没有多解,乙肯定知道是哪两个
#所以删除积的单解
dic=pop(dic,True,False)
#甲:"我也不知道"说明和有多解
#删除和的单解
dic=pop(dic,False,False)
#乙说:"那我知道了"说明积只有一解
#删除积的多解
dic=pop(dic,True,True)
#甲说:"那我也知道了"说明和只有一解
#删除和的多解
dic=pop(dic,False,True)
最终代码:
def pop(dic,is_product,is_single):
lis,lis2=list(zip(*dic.values()))[is_product],[]
for j in lis:
if (lis.count(j) == 1)==is_single:lis2.append(j)
dic={k:v for k,v in dic.items() if v[is_product] in lis2}
return dic
n=30
dic={(a,b):(a+b,a*b) for a in range(1,n+1) for b in range(a+1,n+1)}
dic=pop(dic,True,False)
dic=pop(dic,False,False)
dic=pop(dic,True,True)
dic=pop(dic,False,True)
print(*dic.keys())