Problem:
Score : 300 points

Problem Statement

Takahashi is standing on a multiplication table with infinitely many rows and columns.

The square (i,j) contains the integer i \times j. Initially, Takahashi is standing at (1,1).

In one move, he can move from (i,j) to either (i+1,j) or (i,j+1).

Given an integer N, find the minimum number of moves needed to reach a square that contains N.

Constraints

2 \leq N \leq 10^{12}

N is an integer.

Input

Input is given from Standard Input in the following format:

N

Output

Print the minimum number of moves needed to reach a square that contains the integer N.

Sample Input 1

10

Sample Output 1

5

(2,5) can be reached in five moves. We cannot reach a square that contains 10 in less than five moves.

Sample Input 2

50

Sample Output 2

13

(5, 10) can be reached in 13 moves.

Sample Input 3

10000000019

Sample Output 3

10000000018

Both input and output may be enormous.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using static System.Console;

public static class Program
{
    private static readonly long INF = long.MaxValue / 2;
    private static readonly int MOD = 1000000007;

    struct Pair<T, U> : IComparable<Pair<T, U>>
        where T : IComparable<T>
        where U : IComparable<U>
    {
        public T first;
        public U second;
        private bool CompWithFirst;

        public Pair(T f, U s, int comp)
        {
            first = f;
            second = s;
            CompWithFirst = comp == 1;
        }

        public int CompareTo(Pair<T, U> other)
        {
            return CompWithFirst ? first.CompareTo(other.first) : second.CompareTo(other.second);
        }
    }

    public class PriorityQueue<T> where T : IComparable<T>
    {

        private List<T> Q;
        private readonly int r;

        public PriorityQueue(bool ascending)
        {
            if (ascending)
            {
                r = 1;
            }
            else
            {
                r = -1;
            }

            Q = new List<T>();
        }


        private void PushHeap(List<T> list, T item)
        {
            int n = list.Count();
            list.Add(item);

            while (n != 0)
            {
                int pIndex = (n - 1) / 2;

                if (list[n].CompareTo(list[pIndex]) * r > 0)
                {
                    Swap(Q, n, pIndex);
                }
                else
                {
                    break;
                }

                n = pIndex;
            }
        }

        private void PopHeap(List<T> list)
        {
            int n = list.Count() - 1;
            list[0] = list[n];
            list.RemoveAt(n);

            int cur = 0;
            int comp;

            while (2 * cur + 1 <= n - 1)
            {
                int c1 = 2 * cur + 1;
                int c2 = 2 * (cur + 1);
                if (c1 == n - 1)
                {
                    comp = c1;
                }
                else
                {

                    comp = list[c1].CompareTo(list[c2]) * r > 0 ? c1 : c2;
                }

                if (list[cur].CompareTo(list[comp]) * r < 0)
                {
                    Swap(Q, cur, comp);
                }
                else
                {
                    break;
                }

                cur = comp;
            }
        }

        private void Swap(List<T> list, int a, int b)
        {
            T keep = list[a];
            list[a] = list[b];
            list[b] = keep;
        }



        public void Enqueue(T value)
        {
            PushHeap(Q, value);
        }

        public T Dequeue()
        {
            T ret = Q[0];
            PopHeap(Q);
            return ret;
        }

        public T Peek()
        {
            return Q[0];
        }

        public int CountItem()
        {
            return Q.Count();
        }

        public bool IsEmpty()
        {
            return !Q.Any();
        }
    }

    static long ModInv(long a, long m)
    {
        long b = m, u = 1, v = 0;
        while (b != 0)
        {
            long t = a / b;
            a -= t * b;
            long tmp = a;
            a = b;
            b = tmp;
            u -= t * v;
            tmp = u;
            u = v;
            v = tmp;
        }

        u %= m;
        if (u < 0) u += m;
        return u;
    }

    public static long CalcComb(long n, long m)
    {
        //条件チェック
        if (n < m) return 0;
        if (n < 0 || m < 0) return 0;

        //nＣm ＝ nＣm-1 ×（n-m+1）/ m 
//         return CalcFact(n) / (CalcFact(m) * CalcFact(n - m));
        //MODで割ってbの逆元を求める
        return CalcFact(n) * ModInv((CalcFact(m) * CalcFact(n - m)) % MOD, MOD) % MOD;
    }

    /// <summary>
    /// 階乗を計算する。
    /// </summary>
    /// <param name="n">n</param>
    /// <returns>nの階乗（n!）</returns>
    public static long CalcFact(long n)
    {
        if (n <= 0)
        {
            return 1;
        }

        return n * CalcFact(n - 1) % MOD;
    }


    struct Pos
    {
        public int x;
        public int y;

        public Pos(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        
        public static Pos operator +(Pos p1, Pos p2)
        {
            var result = new Pos();
            result.x = p2.x + p1.x;
            result.y = p2.y + p1.y;
            return result;
        }

        public static Pos operator -(Pos p1, Pos p2)
        {
            var result = new Pos();
            result.x = p2.x - p1.x;
            result.y = p2.y - p1.y;
            return result;
        }
    }
    
    class Modular
    {
        private const int M = 1000000007;
        private long value;

        public Modular(long value)
        {
            this.value = value;
        }

        public static implicit operator Modular(long a)
        {
            var m = a % M;
            return new Modular((m < 0) ? m + M : m);
        }

        public static Modular operator +(Modular a, Modular b)
        {
            return a.value + b.value;
        }

        public static Modular operator -(Modular a, Modular b)
        {
            return a.value - b.value;
        }

        public static Modular operator *(Modular a, Modular b)
        {
            return a.value * b.value;
        }

        private static Modular Pow(Modular a, int n)
        {
            switch (n)
            {
                case 0:
                    return 1;
                case 1:
                    return a;
                default:
                    var p = Pow(a, n / 2);
                    return p * p * Pow(a, n % 2);
            }
        }

        public static Modular operator /(Modular a, Modular b)
        {
            return a * Pow(b, M - 2);
        }

        private static readonly List<int> facs = new List<int> {1};

        private static Modular Fac(int n)
        {
            for (int i = facs.Count; i <= n; ++i)
            {
                facs.Add((int) (Math.BigMul(facs.Last(), i) % M));
            }

            return facs[n];
        }

        public static Modular Ncr(int n, int r)
        {
            return (n < r) ? 0
                : (n == r) ? 1
                : Fac(n) / (Fac(r) * Fac(n - r));
        }

        public static explicit operator int(Modular a)
        {
            return (int) a.value;
        }
    }
    
    static class Permutation<T>
    {
        private static void Search(List<T[]> perms, Stack<T> stack, T[] a)
        {
            int N = a.Length;
            if (N == 0)
            {
                perms.Add(stack.Reverse().ToArray());
            }
            else
            {
                var b = new T[N - 1];
                Array.Copy(a, 1, b, 0, N - 1);
                for (int i = 0; i < a.Length; ++i)
                {
                    stack.Push(a[i]);
                    Search(perms, stack, b);
                    if (i < b.Length) { b[i] = a[i]; }
                    stack.Pop();
                }
            }
        }
        public static IEnumerable<T[]> All(IEnumerable<T> src)
        {
            var perms = new List<T[]>();
            Search(perms, new Stack<T>(), src.ToArray());
            return perms;
        }
    }

    public static int ReadLineToInt()
    {
        return int.Parse(ReadLine());
    }
    
    public static long ReadLineToLong()
    {
        return long.Parse(ReadLine());
    }
    
    public static int[] ReadLineToInts()
    {
        return ReadLine().Split(' ').Select(int.Parse).ToArray();
    }
    
    static int nibunn(int[] array, int target)
    {
        int L = 0;
        int R = array.Length; 
            
        while(R - L > 1)
        {
            int mid = (R + L) / 2;
            if (array[mid] > target) L = mid;
            else R = mid;
        }
        return L;
    }


    public static void Main(string[] args)
    {
        long n = ReadLineToLong();
        long ans = INF;
        for (long i = 1; i * i <= n; i++)
        {
            if (n % i != 0) continue;
            ans = Math.Min(ans, i + (n / i) - 2);
        }
        WriteLine(ans);
    }
}