<p>Given four integers <code>sx</code>, <code>sy</code>, <code>tx</code>, and <code>ty</code>, return <code>true</code><em> if it is possible to convert the point </em><code>(sx, sy)</code><em> to the point </em><code>(tx, ty)</code> <em>through some operations</em><em>, or </em><code>false</code><em> otherwise</em>.</p>

<p>The allowed operation on some point <code>(x, y)</code> is to convert it to either <code>(x, x + y)</code> or <code>(x + y, y)</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> sx = 1, sy = 1, tx = 3, ty = 5
<strong>Output:</strong> true
<strong>Explanation:</strong>
One series of moves that transforms the starting point to the target is:
(1, 1) -&gt; (1, 2)
(1, 2) -&gt; (3, 2)
(3, 2) -&gt; (3, 5)
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> sx = 1, sy = 1, tx = 2, ty = 2
<strong>Output:</strong> false
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> sx = 1, sy = 1, tx = 1, ty = 1
<strong>Output:</strong> true
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= sx, sy, tx, ty &lt;= 10<sup>9</sup></code></li>
</ul>

class Solution:
    def reachingPoints(self, sx: int, sy: int, tx: int, ty: int) -> bool:
        def dfs(x, y):
            # base1; infeasible
            if sx > x or sy > y:
                return False

            # base2; same x values, then only reduce on y
            # (sx, sy) = (x, y) -> (tx, ty) = (x, x + y)
            # valid answer should be ((x + y) - y) % x = 0 
            if x == sx: 
                return (y - sy) % x == 0

            # base3; same y values, then only reduce on x
            # (sx, sy) = (x, y) -> (tx, ty) = (x + y, y)
            # valid answer should be ((x + y) - x) % y = 0 
            if y == sy: 
                return (x - sx) % y == 0

            # seen before
            if (x, y) in memo:
                return memo[(x, y)]

            # otherwise compute memo[(x, y)]

            # case1; under (tx, ty) = (x + y, y), move towards (x, y)
            # meaning (tx, ty) = ((x + y) % y, y) = (x, y)
            case1 = False
            if x > y: 
                case1 = dfs(x % y, y)

            # case2; under (tx, ty) = (x, x + y), move towards (x, y)
            # meaning (tx, ty) = (x, (x + y) % x) = (x, y)
            case2 = False
            if x < y: 
                case2 = dfs(x, y % x)

            # update
            memo[(x, y)] = case1 or case2

            return memo[(x, y)]

        # memo[(x, y)] := True/False if we can find a path converting (x, y) to (sx, sy)
        memo = dict()
        
        return dfs(tx, ty)
16500