两数和&两数积的问题

问题:
有两个数A和B,属于正整数集合[2,99],甲知道两数之和,乙知道两数的乘积,甲跟乙说:我肯定你不知道A和B是什么。乙说:你这么说,那我知道A和B是什么了,甲说:那我也知道了。问:A和B分别是什么?

解答:

# 有两个数A和B,属于正整数集合[2,99],
# 甲知道两数之和,乙知道两数的乘积,
# 甲跟乙说:我肯定你不知道A和B是什么。
# 乙说:你这么说,那我知道A和B是什么了,
# 甲说:那我也知道了。问:A和B分别是什么?

# 我们先从两数和入手:

# 第一轮筛选:
# 甲知道2个数的和,却可以断定乙不知道。那么甲知道的值,一定不是两个质数相加
# 0~100的质数:2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97

prim = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

out1 = [] #两个质数相加的所有可能结果

ans1 = []

for temp1 in prim:
    for temp2 in prim:
        temp = temp1+temp2
        if temp not in out1:
            out1.append(temp)
out1.sort()


for i in range(4,199):
    if i not in out1:
        ans1.append(i)

print(ans1)

# ans1 =
# [11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53, 57,
#  59, 65, 67, 71, 77, 79, 83, 87, 89, 93, 95, 97, 
# 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 
# 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 
# 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 
# 167, 169, 171, 173, 174, 175, 177, 179, 181, 182, 183, 184,
#  185, 187, 188, 189, 190, 191, 192, 193, 195, 196, 197, 198]

# 第二轮筛选:

# 两数和不能太大,单个数不能超过50,因为如果超过50 ,那么我们总是有办法把该数拆解成 一个大于50的质数,在乘以另外一个数。
# 这样我们就无法断定对方不知道了。
# 比如53是一个超过50的质数,那么超过53的数,都可以拆解成53+x,此时,如果知道53*x的乘积,就可以确定推断出是哪两个数的乘积。
# 比如57 = 53 + 4 ,那么乙看到的是53*2*2,他就知道了这两个数一定是53和4.


# ans2 = 
# [11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53]

# 第三轮筛选:
# 乙是怎么知道的?因为甲告诉了乙,这两个数相加只有可能是ans2的值。
# ans2的数都是奇数,所以这必定是一个奇数,一个偶数相加的结果。
# 那么只要因式分解之后,得到的式子中只有n个2和另外一个质数就可以确切的知道是哪两个数。
# 比如乙拿到的是2*2*13,那么他已经知道了结果中有一个奇数,一个偶数,那么他就可以确定一定是4和13
# 遗憾的是,ans2中的所有结果都可以变成 2^n+prim 的形式 ,该条件并没有剔除任何ans2中的值。

# 但甲是怎么知道的?
# 如果是11, 11 = 2*2 + 7 = 2*2*2 + 3
# 甲就无法判断了。
# 那么也就是说,如果ans3中的值 减去pow_2中的值,得到的结果是质数的情况有2种的话。那么甲就无法知道了。

# 代码如下:
pow_2 = [2,4,8,16,32]

ans2 = [11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53]

out3 = []

for temp in ans2:
    count = 0
    for temp2 in prim:
        if(temp > temp2):
            if (temp-temp2) in pow_2:
                count = count+1
                if(temp  not in out3):
                    if(count>1):
                        out3.append(temp)

print("out3:",out3)


ans3 = []

for i in ans2:
    if( i not in out3):
        ans3.append(i)

print(ans3)


# 根据上面论述:
# 11 = 2*2 + 7 = 2*2*2 + 3 , 11 out
# 17 = 2*2 + 13 , 17-2=15,17-8=9,17-16<2 , 这是一组解。
# 23 = 16+7 = 4+19 , 23 out
# 27 = 4+23  = 8+19 , 27 out
# 29 = 16+13 ,这是一组解。
# 35 = 4+31 = 16+19 , 35 out
# 37 = 8+29 = 32+5 , 37 out
# 41 = 4+37 , 这是一组解
# 47 = 16+31 = 4+43 ,47 out
# 51 = 32+19 = 4+47 ,51 out
# 53 = 16+37 , 这是一组解

# 所以ans3 = [17, 29, 41, 53]


# 乙还有什么情况下可以知道呢?
# ans2 = [11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53]
# 如果说 乙拿到的结果是2^n+prim^2 , 且prim不能被任何ans2中的数整除即可。
# 通过这个办法,我们进一步考察ans3中的值。

prim_pow3 = [9,27]
prim_pow5 = [25]
prim_pow7 = [49]

for temp in ans2:
    if(temp%7 == 0):
        print("7:",temp)
    if(temp%5 == 0):
        print("5:",temp)
    if(temp%3 == 0):
        print("3:",temp)



# 17 = 2*2 + 13 
# 17 = 8 + 9

# 如果甲拿到的是17,乙拿到2*2*13当然可以推断出是4,13
# 但是如果乙拿到的是2*2*2*3*3呢?
# 如果是这样,乙无法知道是什么
# 因为此时有2种情况,24+3,8+9 ,都在ans2中。
# 因此乙不可能拿到2*2*2*3*3
# 因此,4,13这一组解,没问题。


# 29 = 16 +13
# 29 = 2 + 27
# 29 = 4 + 25
# 如果甲拿到的是29,乙拿到2*2*2*2*13,当然可以推断出是16,13
# 如果拿到的是2*2*5*5呢?此时乙依然能判断,因为ans2中,只有35是5的倍数。
# 两个2,无论怎么分配,都无法凑出7
# 所以,如果乙拿到2*2*5*5也能判断出这两个数是4,25
# 甲呢?
# 甲无法知道乙拿到的是4,25 还是 16,13
# 因此甲不知道
# 29排除

# 41
# 41 = 4+37
# 41 = 16+25
# 41 = 32+9
# 同理
# 当乙拿到2*2*2*2*5*5 时,2*2*2*2还是无法凑出7.
# 因此,乙还是能知道。
# 但甲就无法知道,到底是(16,25) , 还是(4,37)
# 41排除


# 53
# 53 = 16+37
# 53 = 4+49
# 如果是2*2*7*7时,两个2,刚好可凑出5
# 乙就不知道,甲那边是53,还是35了,乙就不知道了。
# 乙不可能拿到2*2*7*7
# 16,37是一组解。


ans4 = [17,53]

# 我们回到最开始的思路,太大超出范围。
# 如果乙拿到的是6*47,甲拿到的是53
# 甲说乙不可能知道,把答案锁定在ans2,
# 2*3*47, 只有2种可能, (2*47,3),(2*3,47)
# (2*47,3)不再ans2中,所以只能是(2*3,47)
# 也就是说,乙拿到6*47,通过甲说自己知道,是可以排除(2*47,3)
# 当甲拿到53时,乙知道了之后。
# 甲并不知道乙是(6,47)还是(16,37)

ans5 = [17]

#A,B就是(4,13)


猜你喜欢

转载自blog.csdn.net/qq_38307618/article/details/124206695