Problem:
Score : 500 points

Problem Statement

Snuke is conducting an optical experiment using mirrors and his new invention, the rifle of Mysterious Light.

Three mirrors of length N are set so that they form an equilateral triangle.
Let the vertices of the triangle be a, b and c.

Inside the triangle, the rifle is placed at the point p on segment ab such that ap = X.
(The size of the rifle is negligible.)
Now, the rifle is about to fire a ray of Mysterious Light in the direction of bc.

The ray of Mysterious Light will travel in a straight line, and will be reflected by mirrors, in the same ways as "ordinary" light.
There is one major difference, though: it will be also reflected by its own trajectory as if it is a mirror!
When the ray comes back to the rifle, the ray will be absorbed.

The following image shows the ray's trajectory where N = 5 and X = 2.

It can be shown that the ray eventually comes back to the rifle and is absorbed, regardless of the values of N and X.
Find the total length of the ray's trajectory.

Constraints

2≦N≦10^{12}

1≦X≦N-1

N and X are integers.

Partial Points

300 points will be awarded for passing the test set satisfying N≦1000.

Another 200 points will be awarded for passing the test set without additional constraints.

Input

The input is given from Standard Input in the following format:

N X

Output

Print the total length of the ray's trajectory.

Sample Input 1

5 2

Sample Output 1

12

Refer to the image in the Problem Statement section.
The total length of the trajectory is 2+3+2+2+1+1+1 = 12.

Solution in Java7 (OpenJDK 1.7.0) (judge verdict: Time Limit Exceeded)


import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Scanner;
public class Main
{
    private enum Direction
    {
        FLT, ASC, DSC
    }

    private static class Vertex
    {
        Edge in;
        Edge out;
    }

    private static class Edge
    {
        Vertex from;
        Vertex to;
        long len;
        Direction dir;

        public Edge(Vertex f, Vertex t, long len, Direction direction)
        {
            this.from = f;
            this.from.out = this;
            this.to = t;
            this.to.in = this;
            this.len = len;
            this.dir = direction;
        }

        void setTo(Vertex to)
        {
            this.to = to;
            this.to.in = this;
        }

        void setFrom(Vertex from)
        {
            this.from = from;
            this.from.out = this;
        }

        Direction reflect(Direction direction)
        {
            if (this.dir == Direction.FLT)
            {
                if (direction == Direction.ASC)
                    return Direction.DSC;
                else if (direction == Direction.DSC)
                    return Direction.ASC;
                else
                    throw new IllegalArgumentException("Kwap");
            }
            else if (this.dir == Direction.ASC)
            {
                if (direction == Direction.FLT)
                    return Direction.DSC;
                else if (direction == Direction.DSC)
                    return Direction.FLT;
                else
                    throw new IllegalArgumentException("Kwap");
            }
            else if (this.dir == Direction.DSC)
            {
                if (direction == Direction.FLT)
                    return Direction.ASC;
                else if (direction == Direction.ASC)
                    return Direction.DSC;
                else
                    throw new IllegalArgumentException("Kwap");
            }
            else
                throw new IllegalArgumentException("Kwap");
        }

        void reverseGraph()
        {
            Edge currentEdge = this;

            while(true)
            {
                Edge nextEdge = currentEdge.to.out;
                Vertex origFrom = currentEdge.from;
                currentEdge.from = currentEdge.to;
                currentEdge.to = origFrom;

                currentEdge.to.in = currentEdge;
                currentEdge.from.out = currentEdge;

                if (nextEdge.to != currentEdge.from)
                    currentEdge = nextEdge;
                else
                    break;
            }
        }
    }

    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		long x = scan.nextLong();
        System.out.println(getRayLength(x,n)); 
    }

    private static long getRayLength(long X, long N)
    {
        Vertex v1 = new Vertex();
        Vertex v2 = new Vertex();
        Vertex v3 = new Vertex();
        Vertex v4 = new Vertex();

        Edge e1 = new Edge(v1, v2, N - X, Direction.ASC);
        Edge e2 = new Edge(v2, v3, X, Direction.FLT);
        Edge e3 = new Edge(v3, v4, N - X, Direction.DSC);
        Edge e4 = new Edge(v4, v1, N, Direction.FLT);

        return e2.len + trace(Direction.FLT, v3);
    }

    static long trace(Direction inboundDirection, Vertex fromVertex)
    {
        long result = 0;
        while(true)
        {
            Direction reflectedDirection = fromVertex.out.reflect(inboundDirection);
            // Form a triangle..
            if (fromVertex.out.to.out.dir != reflectedDirection && fromVertex.out.to.out.len > fromVertex.out.len)
            {
                // Triangle is formed from clockwise rotation
                long triangleSideLegth = fromVertex.out.len;
                Vertex newVertex = new Vertex();
                fromVertex.out.to.out.setFrom(newVertex);
                fromVertex.out.to.out.len = fromVertex.out.to.out.len - triangleSideLegth;
                fromVertex.out = new Edge(fromVertex, newVertex, triangleSideLegth, reflectedDirection);
                result += triangleSideLegth;
                fromVertex = newVertex;
                inboundDirection = reflectedDirection;
            }
            else if (fromVertex.in.from.in.dir != reflectedDirection && fromVertex.in.from.in.len > fromVertex.in.len)
            {
                // Triangle is formed from counterclockwise rotation
                // Reverse the graph..
                fromVertex.in.reverseGraph();
                long triangleSideLegth = fromVertex.out.len;
                Vertex newVertex = new Vertex();
                fromVertex.out.to.out.setFrom(newVertex);
                fromVertex.out.to.out.len = fromVertex.out.to.out.len - triangleSideLegth;
                fromVertex.out = new Edge(fromVertex, newVertex, triangleSideLegth, reflectedDirection);
                result += triangleSideLegth;
                fromVertex = newVertex;
                inboundDirection = reflectedDirection;
            } else
            {
                // Need to double check that this is correct
                if (fromVertex.in.from.in.len == fromVertex.out.to.out.len)
                {
                    result += fromVertex.in.from.in.len;
                    break;
                }
                else
                    throw new RuntimeException("WhatTheHackException");
            }
        }

        return result;
    }
}