我正在研究一些代码,当需要两个整数m和n时,需要能够有效地预测(最好在O(1)时间内)以下算法的输出。
algorithm(m,n):
history = set()
while True:
if (m,n) in history:
return False
elif n == m:
return True
else:
history.add((m,n))
if m>n:
x = m-n
y = 2*n
m = x
n = y
else:
x = 2*m
y = n-m
m = x
n = y
请注意,当(m,n)出现在以下算法的历史记录中时,您已进入无限循环(即2,1 - > 1,2 - > 2,1 ... );当m == n时,算法可以进一步前进并且必须终止(即5,5-> 10,0-> 10,0 ......)。基本上我需要能够预测m(当前)和n(当前)是否匹配。
PS,如果这个算法有一个名字,我很乐意知道它。此外,如果有关于这个主题的良好阅读(预测数字序列等等),我很乐意被引导到它。答案 0 :(得分:7)
假设正整数输入,当且仅当(m + n)/ gcd(m,n)是2的幂时,此算法将返回True。
证明草图:
在算法开始时将m和n除以gcd(m,n);这不会改变返回值。
如果m和n之和在执行此操作后可以被奇素数p整除,那么m和n都需要被p整除才能使算法返回True,但m和n都不能这样做。
如果m和n的和是2的幂,那么m和n在每次迭代时都会被另一个因子2整除,直到两者相等为止。
答案 1 :(得分:1)
首先,让我们将更新步骤减少到一行。在每次迭代中, m 更新绝对差异; n 更新为较小数字的两倍。
else:
history.add((m,n))
m, n = abs(m-n), 2 * min(m, n)
这突出了迭代的非线性。每次更新都会分为您最初编程的两个类;每次进一步迭代时,重复都会分成多个类。
我认为对此的简短回答是 no - 您无法在比简单执行算法更短的时间内预测结果。
切换大与小的分割点是一个数字是另一个数字的3倍。在那个空间中,算法简单地缩小了间隙:将较小的形式减去较大的形式,然后将较小的形式减去较小的形式。一旦它们进入3倍范围内,系统就会迅速变得混乱:你无法说明随着算法的进展,附近的两对会有结果,而不是任何相邻的对。