最近,我的一位朋友向我提出要求解决这个问题的方法如下:
假设您有两个变量x和y。这些是唯一可用于程序存储的变量。有三种操作可以完成:
现在,您将获得两个数字n1和n2以及目标数字k。从x = n1和y = n2开始,有没有办法使用上面提到的操作到达x = k?如果是,那么可以生成x = k的操作序列是什么。
示例:如果n1 = 16,n2 = 6且k = 28,则答案为是。顺序是:
Operation 1
Operation 1
如果n1 = 19,n2 = 7且k = 22,则答案为是。顺序是:
Operation 2
Operation 3
Operation 1
Operation 1
现在,我已经把问题包围了很长时间,但我没有得到任何初步的想法。我有一种感觉,这是递归,但我不知道边界条件应该是什么。如果有人可以指导我采用可以用来解决这个问题的方法,那将会非常有帮助。谢谢!
答案 0 :(得分:4)
可能不是一个完整的答案,但是当且仅当k
是n1
和n2
的最大公约数(GCD)的倍数时,才能证明序列存在。为简洁起见,我们写G = GCD(n1, n2)
。
首先,我将证明x
和y
始终是G
的整数倍。这种证明通过归纳非常简单。假设:x = p * G
和y = q * G
,对于某些整数p
和q
。
G
。x + y = p * G + q * G = (p + q) * G
x - y = p * G - q * G = (p - q) * G
y - x = q * G - p * G = (q - p) * G
由于此结果,如果k
是k
和n1
的GCD的整数倍,则n2
只能有一个序列。
对于另一个方向,我们需要显示规则可以实现 G
的任何整数倍。如果我们能够达到x = G
和y = G
,情况绝对如此。为此,我们使用Euclid's algorithm。考虑链接的wiki文章中的第二个实现:
function gcd(a, b)
while a ≠ b
if a > b
a := a − b
else
b := b − a
return a
这是规则2和3的重复应用,会产生x = G
和y = G
。
知道存在解决方案,您可以应用BFS(如Amit's answer所示)来查找最短的序列。
答案 1 :(得分:1)
假设存在一个解决方案,可以使用BFS找到最短的序列来完成。
伪代码应该是这样的:
queue <- new empty queue
parent <- new map of type map:pair->pair
parent[(x,y)] = 'root' //special indicator to stop the search there
queue.enqueue(pair(x,y))
while !queue.empty():
curr <- queue.dequeue()
x <- curr.first
y <- curr.second
if x == target or y == target:
printSolAccordingToMap(parent,(x,y))
return
x1 <- x+y
x2 <- x-y
y1 <- x-y
if (x1,y) is not a key in parent:
parent[(x1,y)] = (x,y)
queue.enqueue(pair(x1,y))
//similarly to (x2,y) and (x,y1)
函数printSolAccordingToMap()
只是追溯到地图上,直到找到根,然后打印出来。
请注意,此解决方案仅查找最佳序列(如果存在),但如果不存在则会导致无限循环,因此这只是部分答案。
答案 2 :(得分:0)
考虑到你同时拥有(x,y) always <= target & >0
,如果没有,你可以通过简单的操作将它们带到范围内。如果您考虑这个约束,您可以创建一个图表,其中有O(target*target)
个节点和边缘,您可以通过在该节点上的三个节点之间进行操作来查找。您现在需要评估从起始位置节点到目标节点(target,any)
的最短路径。此处的假设是(x,y)
值始终保持在(0,target)
之内。使用djikstra时间复杂度为O(target*target*log(target))
。
答案 3 :(得分:0)
在Vincent's answer中,我认为证据不完整。
让我们假设两个相对素数假设 n1 = 19 且 n2 = 13 其 GCD 1 。根据他的说法,如果 k 是 GCD 的倍数,则序列退出。因为每个数字都是 1 的倍数。我认为每个 k 都不可能。