using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using Pi = Pair<int, int>;

class Solver
{
    public Scanner sc;
    public void Solve()
    {
        int N, K;
        sc.Make(out N, out K);
        var res = 1L;
        var ct = new int[K+1];
        for(int l = 2; l <= K; l++)
        {
            foreach(var e in Permutations(Enumerable.Range(0, l).ToArray()))
            {
                var c = 0;
                for (int k = 0; k < e.Length; k++) if (k != e[k]) c++;
                if (c == l) ct[l]++;
            }
        }
        for (int k = 2; k <= K; k++)
            res += ct[k] * Perm(N, k) / Perm(k, k);
        Console.WriteLine(res);
    }
    public long Perm(int n,int r)
    {
        return Enumerable.Range(n - r + 1, r).Aggregate(1L, (a, b) => a * b);
    }
    static IEnumerable<T[]> Permutations<T>(T[] array) where T : IComparable<T>
    {
        int index = 0;
        yield return array;
        while (true)
        {
            for (int i = array.Length - 1; i > 0; i--)
            {
                if (array[i - 1].CompareTo(array[i]) >= 0) continue;
                int j = Array.FindLastIndex(array, x => array[i - 1].CompareTo(x) < 0);
                T tmp = array[i - 1]; array[i - 1] = array[j]; array[j] = tmp;
                Array.Reverse(array, i, array.Length - i);
                yield return array;
                goto end;
            }
            Array.Reverse(array, index, array.Length);
            yield break;
        end:;
        }
    }
}

#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var sol = new Solver() { sc = new Scanner() };
        //var th = new Thread(sol.Solve, 1 << 26);th.Start();th.Join();
        sol.Solve();
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static int MaxElement<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    public void Make<T1, T2, T3, T4, T5, T6, T7>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6, out T7 v7) { Make(out v1, out v2, out v3, out v4, out v5, out v6); v7 = Next<T7>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


//#define TESTCASES
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace HackerEarth
{
    /// <summary>
    /// Solution class
    /// </summary>
    internal static class Program
    {
        #region Main
        /// <summary>
        /// Modulo operator used in a lot of questions
        /// </summary>
        private const long mod = 1000000007L;

        /// <summary>
        /// Fast Console IO helper
        /// </summary>
        private static ConsoleHelper Console { get; } = new ConsoleHelper();

        /// <summary>
        /// Main method - Launches solver
        /// </summary>
        private static void Main()
        {
            using (Console)
            {
#if DEBUG
                Stopwatch timer = Stopwatch.StartNew();
#endif

#if TESTCASES
                TestCases();
#else //!TESTCASES
                Solve();
#endif
#if DEBUG
                timer.Stop();
               // Console.Write($"\r\nTotal run time: {timer.Elapsed.TotalSeconds:0.000}s");
#endif
            }
        }

#if TESTCASES
        /// <summary>
        /// Solves the problem for multiple test cases
        /// </summary>
        private static void TestCases()
        {
            int t = Console.NextInt();
            Console.SkipNextLine();

			    while (t-- > 0)
            {

                Solve();
            }
            //Console.WriteLine();
        }

#endif
        #endregion

        #region Solution

static int []id;
 static   int root(int x)
{
    while(id[x] != x)
    {
        id[x] = id[id[x]];
        x = id[x];
    }
    return x;
}

static void union1(int x, int y)
{
    int p = root(x);
    int q = root(y);
    id[p] = id[q];
}

static long gcd(int a,int b)
{

    if(a==0)
    return (long)b;
    return gcd(b%a,a);
}

        /// <summary>
        /// Solution
        /// </summary>
        private static void Solve()
        {

         long n=Console.NextInt();
         long k=Console.NextInt();
         long sum=1;
         if(k>1&&k>=2)
         sum+=(n*(n-1))/2;
         if(k>1&&k>=3)
         sum+=(n*(n-1)*(n-2))/3;
         if(k>1&&k>=4)
         sum+=(n*(n-1)*(n-2)*(n-3)*6)/16;

        Console.WriteLine(sum);

        }
        #endregion
    }

    #region Tools
    //Solution does not extend beyond this point, those are merely tools to help along
    /// <summary>
    /// Fast Console IO helper
    /// </summary>
    [DebuggerStepThrough]
    internal sealed class ConsoleHelper : IDisposable
    {
        #region Constants
        /// <summary>
        /// The standard input and output buffers size (2^20, 1Mb)
        /// </summary>
        private const int baseSize = 1048576;
        /// <summary>
        /// Integer out string conversion buffer
        /// </summary>
        private static readonly char[] numBuffer = new char[20];
        #endregion

        #region Fields
        private readonly BufferedStream inStream; //Buffered console input stream
        private readonly StreamWriter outStream; //Buffered console output stream

        private readonly byte[] inBuffer; //Input buffer
        private int inputIndex; //Input buffer current index
        private int bufferEnd; //Input buffer ending index
        #endregion

        #region Properties
        /// <summary>
        /// The buffer size, in bytes
        /// </summary>
        public int BufferSize { get; }

        /// <summary>
        /// If this memory stream is open and available to read/write
        /// </summary>
        public bool Open { get; private set; }
        #endregion

        #region Constructors
        /// <summary>
        /// Creates a new console IO helper reading from the standard Console input and output
        /// </summary>
        public ConsoleHelper() : this(baseSize) { }

        /// <summary>
        /// Creates a new console IO helper reading from the standard Console input and output with the specified buffer size
        /// <param name="bufferSize">Size of the buffer to use in bytes</param>
        /// </summary>
        public ConsoleHelper(int bufferSize)
        {
            //Open the input/output streams
#if DEBUG
            //Test mode
            this.inStream = new BufferedStream(File.OpenRead(@"input.txt"), bufferSize);
            this.outStream = new StreamWriter(File.Create(@"output.txt", bufferSize), Encoding.ASCII, bufferSize);
#else //!DEBUG
//Submission mode
            this.inStream = new BufferedStream(Console.OpenStandardInput(bufferSize), bufferSize); //Submission stream
            this.outStream = new StreamWriter(Console.OpenStandardOutput(bufferSize), Encoding.ASCII, bufferSize);
#endif

            //Set fields
            this.inBuffer = new byte[bufferSize];
            this.inputIndex = this.bufferEnd = 0;
            this.BufferSize = bufferSize;
            this.Open = true;
        }
        #endregion

        #region Static methods
        /// <summary>
        /// Verifies that the passed character is a non-special ASCII character
        /// </summary>
        /// <param name="i">Character to validate</param>
        /// <returns>True if the character is not a special character</returns>
        public static bool ValidateChar(int i) => i >= ' ';

        /// <summary>
        /// Verifies that the passed character is a non-special ASCII character or a whitespace
        /// </summary>
        /// <param name="i">Character to validate</param>
        /// <returns>True if the character is not a whitespace or a special character</returns>
        public static bool ValidateCharNoSpace(int i) => i > ' ';

        /// <summary>
        /// Verifies that the passed character is a numerical character (0-9)
        /// </summary>
        /// <param name="i">Character to validate</param>
        /// <returns>True if the character is a numerical character, false otherwise</returns>
        public static bool ValidateNumber(int i) => i >= '0' && i <= '9';

        /// <summary>
        /// Verifies if a character is an Endline character
        /// </summary>
        /// <param name="i">Character to check</param>
        /// <returns>True if it is an Endline character, false otherwise</returns>
        public static bool IsEndline(int i) => i == '\n' || i == '\0';

        /// <summary>
        /// Takes a signed int value and copies it's characters at the end of the integer char buffer
        /// </summary>
        /// <param name="n">Int to write to the buffer</param>
        /// <returns>Head index at which the buffer's writing starts</returns>
        private static int GetIntBuffer(int n)
        {
            int head = 20;
            bool neg;
            if (n < 0)
            {
                neg = true;
                n = -n;
            }
            else { neg = false; }

            do
            {
                numBuffer[--head] = (char)((n % 10) + 48);
                n /= 10;
            }
            while (n > 0);

            if (neg) { numBuffer[--head] = '-'; }
            return head;
        }

        /// <summary>
        /// Takes a signed long value and copies it's characters at the end of the integer char buffer
        /// </summary>
        /// <param name="n">Long to write to the buffer</param>
        /// <returns>Head index at which the buffer's writing starts</returns>
        private static int GetLongBuffer(long n)
        {
            int head = 20;
            bool neg;
            if (n < 0L)
            {
                neg = true;
                n = -n;
            }
            else { neg = false; }

            do
            {
                numBuffer[--head] = (char)((n % 10L) + 48L);
                n /= 10L;
            }
            while (n > 0L);

            if (neg) { numBuffer[--head] = '-'; }
            return head;
        }
        #endregion

        #region Methods
        /// <summary>
        /// Returns the next byte data in the console input stream
        /// </summary>
        /// <returns>Next data byte from the console</returns>
        public byte Read()
        {
            CheckBuffer();
            return this.inBuffer[this.inputIndex++];
        }

        /// <summary>
        /// Returns the next byte data in the console input stream without consuming it
        /// </summary>
        /// <returns>Next data byte from the console</returns>
        public byte Peek()
        {
            CheckBuffer();
            return this.inBuffer[this.inputIndex];
        }

        /// <summary>
        /// Skips a number of characters in the input stream
        /// </summary>
        /// <param name="n">Amount of chars to skip, defaults to 1</param>
        public void Skip(int n = 1) => this.inputIndex += n;

        /// <summary>
        /// Assures we have data available in the input buffer
        /// </summary>
        private void CheckBuffer()
        {
            //If we reach the end of the buffer, load more data
            if (this.inputIndex >= this.bufferEnd)
            {
                this.inputIndex = this.inputIndex - this.bufferEnd;
                this.bufferEnd = this.inStream.Read(this.inBuffer, 0, this.BufferSize);

                //If nothing was added, add a null char at the start
                if (this.bufferEnd < 1) { this.inBuffer[this.bufferEnd++] = 0; }
            }
        }

        public char NextChar() => (char)Read();

                public string Next()
        {
            byte b = SkipInvalid();
            ValidateEndline(b);

            //Append all characters
            StringBuilder sb = new StringBuilder().Append((char)b);
            b = Peek();
            while (ValidateCharNoSpace(b))
            {
                //Peek to not consume terminator
                sb.Append((char)b);
                Skip();
                b = Peek();
            }

            return sb.ToString();
        }

        public int NextInt()
        {
            //Skip invalids
            byte b = SkipInvalid();
            ValidateEndline(b);

            //Verify for negative
            bool neg = false;
            if (b == '-')
            {
                neg = true;
                b = Read();
            }

            //Get first digit
            if (!ValidateNumber(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }

            int n = b - '0';
            b = Peek();
            while (ValidateNumber(b))
            {
                //Peek to not consume terminator, and check for overflow
                n = checked((n << 3) + (n << 1) + (b - '0'));
                Skip();
                b = Peek();
            }
            //If the character causing the exit is a valid ASCII character, the integer isn't correct formatted
            if (ValidateCharNoSpace(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }

            return neg ? -n : n;
        }

        public long NextLong()
        {
            byte b = SkipInvalid();
            ValidateEndline(b);

            //Verify negative
            bool neg = false;
            if (b == '-')
            {
                neg = true;
                b = Read();
            }

            //Get first digit
            if (!ValidateNumber(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }

            long n = b - '0';
            b = Peek();
            while (ValidateNumber(b))
            {
                //Peek to not consume terminator, and check for overflow
                n = checked((n << 3) + (n << 1) + (b - '0'));
                Skip();
                b = Peek();
            }
            //If the character causing the exit is a valid ASCII character, the long isn't correct formatted
            if (ValidateCharNoSpace(b)) { throw new FormatException("Long parsing has failed because the string contained invalid characters"); }

            return neg ? -n : n;
        }

        public double NextDouble() => double.Parse(Next());

        public int[] NextInts(int n)
        {
            int[] array = new int[n];
            for (int i = 0; i < n; i++)
            {
                array[i] = NextInt();
            }

            SkipNextLine();
            return array;
        }

        public long[] NextLongs(int n)
        {
            long[] array = new long[n];
            for (int i = 0; i < n; i++)
            {
                array[i] = NextLong();
            }

            SkipNextLine();
            return array;
        }

        public int[,] NextMatrix(int n, int m)
        {
            int[,] matrix = new int[n, m];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    matrix[i, j] = NextInt();
                }

                SkipNextLine();
            }

            return matrix;
        }

        /// <summary>
        /// Returns the next line of text in the console
        /// </summary>
        /// <returns>Next string line from the console</returns>
        public string NextLine()
        {
            byte b = SkipInvalid();
            if (b == 0)
            {
                //Consume newline and return empty string
                Skip();
                return string.Empty;
            }

            //Read all the characters until the next linefeed
            StringBuilder sb = new StringBuilder().Append((char)b);
            b = Read();
            while (!IsEndline(b))
            {
                //Don't append special characters, but don't exit
                if (ValidateChar(b))
                {
                    sb.Append((char)b);
                }
                b = Read();
            }

            return sb.ToString();
        }

        /// <summary>
        /// Skips the next token in input
        /// </summary>
        /// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
        public void SkipNext()
        {
            byte b = SkipInvalid();
            ValidateEndline(b);

            for (b = Peek(); ValidateCharNoSpace(b); b = Peek())
            {
                Skip();
            }
        }

        /// <summary>
        /// Skips all the text on the current line and jump to the next
        /// </summary>
        public void SkipNextLine()
        {
            for (byte b = Read(); !IsEndline(b); b = Read()) { }
        }

        public IEnumerable<int> EnumerateInts(int n)
        {
            while (n-- > 0)
            {
                yield return NextInt();
            }

            SkipNextLine();
        }

        /// <summary>
        /// Enumerates all the characters in the next line until the feed is exhausted or an endline character is met
        /// </summary>
        /// <returns>Enumerable of all the characters in the current line</returns>
        public IEnumerable<char> EnumerateLine()
        {
            for (char c = NextChar(); !IsEndline(c); c = NextChar())
            {
                if (ValidateChar(c))
                {
                    yield return c;
                }
            }
        }

        /// <summary>
        /// Assures we are not trying to read more data on the line that there exists
        /// </summary>
        /// <param name="b">Byte data to verify</param>
        /// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
        private void ValidateEndline(byte b)
        {
            //If empty char
            if (b == 0)
            {
                //Go back a char and throw
                this.inputIndex--;
                throw new InvalidOperationException("No values left on line");
            }
        }

        /// <summary>
        /// Skips all invalid character bytes then returns the first valid byte found, spaces are considered invalid
        /// </summary>
        /// <returns>The next valid character byte, cannot be a whitespace</returns>
        private byte SkipInvalid()
        {
            byte b = Peek();
            if (IsEndline(b)) { return 0; }

            while (!ValidateCharNoSpace(b))
            {
                Skip();
                b = Peek();
                //Return empty char if we meet an linefeed or empty char
                if (IsEndline(b)) { return 0; }
            }

            return Read();
        }

        /// <summary>
        /// Writes the given char to the console output
        /// </summary>
        /// <param name="c">Character to write</param>
        public void Write(char c) => this.outStream.Write(c);

        /// <summary>
        /// Writes the given char buffer to the console output
        /// </summary>
        /// <param name="buffer">Char buffer to write</param>
        public void Write(char[] buffer) => this.outStream.Write(buffer);

        /// <summary>
        /// Writes the given string to the console output
        /// </summary>
        /// <param name="s">String to write</param>
        public void Write(string s) => this.outStream.Write(s);

        /// <summary>
        /// Writes the given integer to the console output
        /// </summary>
        /// <param name="n">Integer to write</param>
        public void Write(int n)
        {
            int head = GetIntBuffer(n);
            this.outStream.Write(numBuffer, head, 20 - head);
        }

        /// <summary>
        /// Writes the given long to the console output
        /// </summary>
        /// <param name="n">Long to write</param>
        public void Write(long n)
        {
            int head = GetLongBuffer(n);
            this.outStream.Write(numBuffer, head, 20 - head);
        }

        /// <summary>
        /// Writes the contents of the StringBuilder to the console output
        /// </summary>
        /// <param name="sb">StringBuilder to write to the output</param>
        public void Write(StringBuilder sb) => this.outStream.Write(sb.ToCharArray());

        /// <summary>
        /// Writes the given object to the console output using the object's ToString method
        /// </summary>
        /// <param name="o">Object to write</param>
        public void Write(object o) => this.outStream.Write(o);

        /// <summary>
        /// Writes a sequence to the console output with the given string separator
        /// </summary>
        /// <typeparam name="T">Type of elements in the sequence</typeparam>
        /// <param name="e">Sequence to print</param>
        /// <param name="separator">String separator between each element, defaults to the empty string</param>
        public void Write<T>(IEnumerable<T> e, string separator = "") => this.outStream.Write(new StringBuilder().AppendJoin(e, separator).ToCharArray());

        /// <summary>
        /// Writes a sequence to the console output with the given string separator
        /// </summary>
        /// <typeparam name="T">Type of elements in the sequence</typeparam>
        /// <param name="e">Sequence to print</param>
        /// <param name="separator">Character separator between each element</param>
        public void Write<T>(IEnumerable<T> e, char separator) => this.outStream.Write(new StringBuilder().AppendJoin(e, separator).ToCharArray());

        /// <summary>
        /// Writes a linefeed to the console output
        /// </summary>
        public void WriteLine() => this.outStream.WriteLine();

        /// <summary>
        /// Writes the given char to the console output, followed by a linefeed
        /// </summary>
        /// <param name="c">Character to write</param>
        public void WriteLine(char c) => this.outStream.WriteLine(c);

        /// <summary>
        /// Writes the given char buffer to the console output, followed by a linefeed
        /// </summary>
        /// <param name="buffer">Char buffer to write to the output</param>
        public void WriteLine(char[] buffer) => this.outStream.WriteLine(buffer);

        /// <summary>
        /// Writes the given string to the console output, followed by a linefeed
        /// </summary>
        /// <param name="s">String to write</param>
        public void WriteLine(string s) => this.outStream.WriteLine(s);

        /// <summary>
        /// Writes the given integer to the console output, followed by a linefeed
        /// </summary>
        /// <param name="n">Integer to write</param>
        public void WriteLine(int n)
        {
            int head = GetIntBuffer(n);
            this.outStream.WriteLine(numBuffer, head, 20 - head);
        }

        /// <summary>
        /// Writes the given long to the console output, followed by a linefeed
        /// </summary>
        /// <param name="n">Long to write</param>
        public void WriteLine(long n)
        {
            int head = GetLongBuffer(n);
            this.outStream.WriteLine(numBuffer, head, 20 - head);
        }

        /// <summary>
        /// Writes the contents of the StringBuilder to the console output, followed by a linefeed
        /// </summary>
        /// <param name="sb">StringBuilder to write to the output</param>
        public void WriteLine(StringBuilder sb) => this.outStream.WriteLine(sb.ToCharArray());

        /// <summary>
        /// Writes a sequence to the console output with the given string separator, follows by a linefeed
        /// </summary>
        /// <typeparam name="T">Type of elements in the sequence</typeparam>
        /// <param name="e">Sequence to print</param>
        /// <param name="separator">String separator between each element, defaults to the empty string</param>
        public void WriteLine<T>(IEnumerable<T> e, string separator = "") => this.outStream.WriteLine(new StringBuilder().AppendJoin(e, separator).ToCharArray());

        /// <summary>
        /// Writes a sequence to the console output with the given string separator, follows by a linefeed
        /// </summary>
        /// <typeparam name="T">Type of elements in the sequence</typeparam>
        /// <param name="e">Sequence to print</param>
        /// <param name="separator">Character separator between each element</param>
        public void WriteLine<T>(IEnumerable<T> e, char separator) => this.outStream.WriteLine(new StringBuilder().AppendJoin(e, separator).ToCharArray());

        /// <summary>
        /// Writes the given object to the console output using the object's ToString method, followed by a linefeed
        /// </summary>
        /// <param name="o">Object to write</param>
        public void WriteLine(object o) => this.outStream.WriteLine(o);

        /// <summary>
        /// Flushes the output buffer to the console if the buffer is full, or if it's being forced
        /// </summary>
        public void Flush() => this.outStream.Flush();

        /// <summary>
        /// Disposes of the resources of this ConsoleHelper, closing all the associated streams
        /// </summary>
        public void Dispose()
        {
            if (this.Open)
            {
                Flush();
                this.inStream.Dispose();
                this.outStream.Dispose();
                this.Open = false;
            }
        }
        #endregion
    }

    /// <summary>
    /// Useful extensions
    /// </summary>
    internal static class Extensions
    {
        #region Enumerable extensions

        public static string Join<T>(this IEnumerable<T> e, string separator = "") => new StringBuilder().AppendJoin(e, separator).ToString();

        public static string Join<T>(this IEnumerable<T> e, char separator) => new StringBuilder().AppendJoin(e, separator).ToString();

        public static T MinValue<T, TU>(this IEnumerable<T> e, Func<T, TU> selector) where TU : IComparable<TU>
        {
            using (IEnumerator<T> enumerator = e.GetEnumerator())
            {
                if (!enumerator.MoveNext()) { throw new InvalidOperationException("No elements in sequence"); }

                T min = enumerator.Current;
                TU value = selector(min);
                while (enumerator.MoveNext())
                {
                    TU v = selector(enumerator.Current);
                    if (value.CompareTo(v) > 0)
                    {
                        min = enumerator.Current;
                        value = v;
                    }
                }

                return min;
            }
        }
        #endregion

        #region String extensions
        /// <summary>
        /// Appends multiple objects to a StringBuilder, separated by the given string
        /// </summary>
        /// <typeparam name="T">Type of elements in the Enumerable</typeparam>
        /// <param name="sb">StringBuilder to append to</param>
        /// <param name="source">Enumerable to loop through</param>
        /// <param name="separator">Separator string, defaults to the empty string</param>
        /// <returns>The StringBuilder instance after the appending is done</returns>
        public static StringBuilder AppendJoin<T>(this StringBuilder sb, IEnumerable<T> source, string separator = "")
        {
            using (IEnumerator<T> e = source.GetEnumerator())
            {
                if (e.MoveNext())
                {
                    sb.Append(e.Current);
                    while (e.MoveNext())
                    {
                        sb.Append(separator).Append(e.Current);
                    }
                }
            }

            return sb;
        }

        /// <summary>
        /// Appends multiple objects to a StringBuilder, separated by the given string
        /// </summary>
        /// <typeparam name="T">Type of elements in the Enumerable</typeparam>
        /// <param name="sb">StringBuilder to append to</param>
        /// <param name="source">Enumerable to loop through</param>
        /// <param name="separator">Separator character</param>
        /// <returns>The StringBuilder instance after the appending is done</returns>
        public static StringBuilder AppendJoin<T>(this StringBuilder sb, IEnumerable<T> source, char separator)
        {
            using (IEnumerator<T> e = source.GetEnumerator())
            {
                if (e.MoveNext())
                {
                    sb.Append(e.Current);
                    while (e.MoveNext())
                    {
                        sb.Append(separator).Append(e.Current);
                    }
                }
            }

            return sb;
        }

        /// <summary>
        /// Returns true if the string is null, or the empty string ""
        /// Note: this will never throw a NullRef exception given that it is an extension method calling a static method
        /// </summary>
        /// <param name="s">String to test</param>
        /// <returns>True if the string is null or empty, false otherwise</returns>
        public static bool IsEmpty(this string s) => string.IsNullOrEmpty(s);

        /// <summary>
        /// Creates a substring from a starting and ending index
        /// </summary>
        /// <param name="s">String to substring</param>
        /// <param name="start">Starting index</param>
        /// <param name="end">Ending index</param>
        /// <returns>The resulting substring</returns>
        public static string SubStr(this string s, int start, int end) => s.Substring(start, (end - start) + 1);

        /// <summary>
        /// Copies the contents of a StringBuilder instance to an array
        /// </summary>
        /// <param name="sb">StringBuilder to copy</param>
        /// <returns>Contents array of the StringBuilder</returns>
        public static char[] ToCharArray(this StringBuilder sb)
        {
            char[] buffer = new char[sb.Length];
            sb.CopyTo(0, buffer, 0, sb.Length);
            return buffer;
        }
        #endregion

        #region Number extensions
        /// <summary>
        /// Tests if the given number is pair or not
        /// </summary>
        /// <param name="n">Number to test</param>
        /// <returns>True if the number is pair, false otherwise</returns>
        public static bool IsPair(this int n) => (n & 1) == 0;

        /// <summary>
        /// Tests if the given number is pair or not
        /// </summary>
        /// <param name="n">Number to test</param>
        /// <returns>True if the number is pair, false otherwise</returns>
        public static bool IsPair(this long n) => (n & 1L) == 0;

        /// <summary>
        /// Real Modulus function over the integer, not a remainder function like the normal C# mod
        /// </summary>
        /// <param name="n">Left operand of the mod</param>
        /// <param name="m">Right operand of the mod</param>
        /// <returns>The Modulus of n and m, within [0, m - 1]</returns>
        public static int Mod(this int n, int m) => ((n % m) + m) % m;

        /// <summary>
        /// Real Modulus function over the integer, not a remainder function like the normal C# mod
        /// </summary>
        /// <param name="n">Left operand of the mod</param>
        /// <param name="m">Right operand of the mod</param>
        /// <returns>The Modulus of n and m, within [0, m - 1]</returns>
        public static long Mod(this long n, long m) => ((n % m) + m) % m;

        /// <summary>
        /// Returns the triangle number of the current number
        /// </summary>
        /// <param name="n">Integer to get the triangle number from</param>
        /// <returns>The resulting triangle number</returns>
        public static int Triangle(this int n) => (n * (n + 1)) / 2;

        /// <summary>
        /// Returns the triangle number of the current number
        /// </summary>
        /// <param name="n">Long to get the triangle number from</param>
        /// <returns>The resulting triangle number</returns>
        public static long Triangle(this long n) => (n * (n + 1L)) / 2L;

        /// <summary>
        /// Counts the amount of set bits (1s in the binary representation) of a given integer
        /// </summary>
        /// <param name="n">Integer to get the set bits from</param>
        /// <returns>Amount of set bits of the integer</returns>
        public static int SetBits(this int n)
        {
            n = n - ((n >> 1) & 0x55555555);
            n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
            return (((n + (n >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
        }

        /// <summary>
        /// Counts the amount of set bits (1s in the binary representation) of a given long
        /// </summary>
        /// <param name="n">Long to get the set bits from</param>
        /// <returns>Amount of set bits of the long</returns>
        public static long SetBits(this long n)
        {
            n = n - ((n >> 1) & 0x5555555555555555);
            n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333);
            return (((n + (n >> 4)) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56;
        }
        #endregion

        #region Array extensions
        /// <summary>
        /// Does a binary search through the sorted array to find the requested value
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="value">Value to find</param>
        /// <returns>The index of the found element, or -1 if it wasn't found</returns>
        public static int BinarySearch<T>(this T[] array, T value) => Array.BinarySearch(array, value);

        /// <summary>
        /// Clears the array of all elements
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to clear</param>
        public static void Clear<T>(this T[] array) => Array.Clear(array, 0, array.Length);

        /// <summary>
        /// Determines if the array contains the given value
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="value">Value to find</param>
        /// <returns>True if the value was found, false otherwise</returns>
        public static bool Contains<T>(this T[] array, T value) => Array.IndexOf(array, value) != -1;

        /// <summary>
        /// Enumerates the contents of an ArraySegment
        /// </summary>
        /// <typeparam name="T">Type contained within the array</typeparam>
        /// <param name="array">Array to iterate through</param>
        /// <param name="offset">Index offset to start the iteration at, defaults to 0</param>
        /// <param name="count">Amount of values to return, default to the whole array</param>
        /// <returns>Enumerable of all the values contained in the ArraySegment</returns>
        public static IEnumerable<T> Enumerate<T>(this T[] array, int offset = 0, int count = 0)
        {
            if (count == 0) { count = array.Length - offset; }

            int max = offset + count;
            for (int i = offset; i < max; i++)
            {
                yield return array[i];
            }
        }

        /// <summary>
        /// Sees if an elements matching the specified condition exists in the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="match">Matching function to apply</param>
        /// <returns>True if a matching element exists, false otherwise</returns>
        public static bool Exists<T>(this T[] array, Predicate<T> match) => Array.Exists(array, match);

        /// <summary>
        /// Finds the first element matching the given condition in the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="match">Matching function to apply</param>
        /// <returns>The first found element that satisfied the match, or default(T) if none did</returns>
        public static T Find<T>(this T[] array, Predicate<T> match) => Array.Find(array, match);

        /// <summary>
        /// Finds the last element matching the given condition in the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="match">Matching function to apply</param>
        /// <returns>The last found element that satisfied the match, or default(T) if none did</returns>
        public static T FindLast<T>(this T[] array, Predicate<T> match) => Array.FindLast(array, match);

        /// <summary>
        /// Applies an action to every member of the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to loop through</param>
        /// <param name="action">Action to apply on each member</param>
        public static void ForEach<T>(this T[] array, Action<T> action) => Array.ForEach(array, action);

        /// <summary>
        /// Generates all the subsets of the given array of a size greater than or equal 1
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to get the subsets from</param>
        /// <returns>All the subsets of size 1 or greater from the array</returns>
        public static IEnumerable<List<T>> GetSubsets<T>(this T[] array)
        {
            int max = 1 << array.Length, l = array.Length - 1;
            for (int i = 1; i < max; i++)
            {
                if ((i & -i) == i) { continue; } //Exclude subsets of length 1

                List<T> subset = new List<T>(array.Length);
                subset.AddRange(array.Where((t, j) => (i & (1 << (l - j))) != 0));
                yield return subset;
            }
        }

        /// <summary>
        /// Finds the first index of the given value in the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="value">Value to find</param>
        /// <returns>The index of the value in the array, or -1 if it wasn't found</returns>
        public static int IndexOf<T>(this T[] array, T value) => Array.IndexOf(array, value);

        /// <summary>
        /// Finds the last index of the given value in the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to search into</param>
        /// <param name="value">Value to find</param>
        /// <returns>The last index of the value in the array, or -1 if it wasn't found</returns>
        public static int LastIndexOf<T>(this T[] array, T value) => Array.LastIndexOf(array, value);

        /// <summary>
        /// Reverses the array
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to reverse</param>
        /// <returns>The reversed array</returns>
        public static T[] Reverse<T>(this T[] array)
        {
            Array.Reverse(array);
            return array;
        }

        /// <summary>
        /// Sorts the array with the default comparer of T
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to sort</param>
        public static void Sort<T>(this T[] array) => Array.Sort(array);

        /// <summary>
        /// Sorts an array with the given comparison method
        /// </summary>
        /// <typeparam name="T">Type of elements in the array</typeparam>
        /// <param name="array">Array to sort</param>
        /// <param name="comparison">Comparison method to sort the array with</param>
        public static void Sort<T>(this T[] array, Comparison<T> comparison) => Array.Sort(array, comparison);

        /// <summary>
        /// Swap two elements in an array
        /// </summary>
        /// <typeparam name="T">Type of the array</typeparam>
        /// <param name="array">Aray to swap elements in</param>
        /// <param name="i">Index of the first element</param>
        /// <param name="j">Index of the second element</param>
        public static void Swap<T>(this T[] array, int i, int j)
        {
            T t = array[i];
            array[i] = array[j];
            array[j] = t;
        }

        public static void heapadd(this List<int> l, int i)
        {
            l.Add(i);
            for (int j = l.Count - 1; j >= 0;)
            {
                int t = (j - 1) / 2;
                if (l[j] < l[t])
                {
                    int temp = l[t];
                    l[t] = l[j];
                    l[j] = temp;
                }
                else
                    break;
                j = t;
            }
        }
        public static int heapdelete(this List<int> l)
        {
            int le = l.Count;
            int t = l[0];
            l[0] = l[le - 1];
            l.RemoveAt(le - 1);
            for (int i = 0; i < le - 1;)
            {
                int y = 2 * i + 1;
                if (y + 1 >= le - 1)
                {
                    if (y >= le - 1)
                        break;
                    if (l[i] > l[y])
                    {
                        int temp = l[y];
                        l[y] = l[i];
                        l[i] = temp;

                    }
                    break;
                }
                if (l[y] > l[y + 1])
                {
                    if (l[i] > l[y + 1])
                    {
                        int temp = l[y + 1];
                        l[y + 1] = l[i];
                        l[i] = temp;
                        i = y + 1;
                    }
                    else
                        break;
                }
                else
                {
                    if (l[i] > l[y])
                    {
                        int temp = l[y];
                        l[y] = l[i];
                        l[i] = temp;
                        i = y;
                    }
                    else
                        break;
                }
            }

            return t;
        }

        #endregion
    }
    #endregion
}


using System;
using System.IO;
using System.Text;

namespace Almost_Identity_Permutations
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);
        private static readonly long[,] C = new long[1000,5];

        private static void Main(string[] args)
        {
            writer.WriteLine(Solve(args));
            writer.Flush();
        }

        private static long Solve(string[] args)
        {
            int n = Next();
            int k = Next();

            long ans = 1;
            var m = new[] {0, 1, 1, 2, 9};
            for (int i = 2; i <= k; i++)
            {
                ans += GetC(n, i)*m[i];
            }

            return ans;
        }

        private static long GetC(int n, int k)
        {
            if (n < k)
            {
                int c = k;
                k = n;
                n = c;
            }
            if (k == 0 || k == n)
                return 1;

            if (C[n, k] != 0)
                return C[n, k];

            return C[n, k] = GetC(n - 1, k - 1) + GetC(n - 1, k);
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        string S = sc.Str, T = sc.Str;
        bool[] uses = new bool[S.Length], uset = new bool[T.Length];
        var dp = Create(S.Length + 1, () => new int[T.Length+1]);
        for(int i=0;i<S.Length;i++)
            for(int j=0;j<T.Length;j++)
                if (S[i] == T[j])
                {
                    dp[i+1][j+1] = dp[i][j] + 1;
                }
                else
                {
                    dp[i + 1][j + 1] = Max(dp[i + 1][j], dp[i][j + 1]);
                }
        int s = S.Length, t = T.Length;
        while (s != 0 && t != 0)
        {
            if (S[s - 1] == T[t - 1])
            {
                uses[s - 1] = uset[t - 1] = true;
                s--;t--;
            }
            else
            {
                if (dp[s - 1][t] == dp[s][t])
                {
                    s--;
                }
                else t--;
            }
        }
        int idx = 0;
        for(int i = 0; i < S.Length; )
        {
            var ct = 0;
            while (idx < S.Length && S[i] == S[idx])
            {
                if (uses[idx]) ct++;
                idx++;
            }
            for (int j = i; j < idx; j++)
                uses[j] = false;
            if (S[i] == ')')
            {
                for (int j = i; j < i + ct; j++)
                    uses[j] = true;
            }
            else
            {
                for (int j = idx - 1; j >= idx - ct; j--)
                    uses[j] = true;
            }
            i = idx;
        }
       idx = 0;
        for (int i = 0; i < T.Length;)
        {
            var ct = 0;
            while (idx < T.Length && T[i] == T[idx])
            {
                if (uset[idx]) ct++;
                idx++;
            }
            for (int j = i; j < idx; j++)
                uset[j] = false;
            if (T[i] == ')')
            {
                for (int j = i; j < i + ct; j++)
                    uset[j] = true;
            }
            else
            {
                for (int j = idx - 1; j >= idx - ct; j--)
                    uset[j] = true;
            }
            i = idx;
        }
        s = 0;t = 0;var st = 0;
        var res = new List<char>();
        while (s < S.Length || t < T.Length)
        {
            int op = 0, cl = 0;
            while (s < S.Length && !uses[s])
            {
                if (S[s] == '(') op++;
                else cl++;
                s++;
            }
            while (t < T.Length && !uset[t])
            {
                if (T[t] == '(') op++;
                else cl++;
                t++;
            }
            st += op;
            st -= cl;
            while (st < 0) { st++; res.Add('('); }
            while (op-- > 0) res.Add('(');
            while (cl-- > 0) res.Add(')');
            if (s != S.Length)
            {
                if (S[s] == '(') st++;
                else st--;
                while (st < 0) { st++; res.Add('('); }

                res.Add(S[s]);
            }
            s++;t++;
        }
        var r = new List<char>();
        while (st < 0) { r.Add('('); st++; }
        r.AddRange(res);
        while (st-- > 0) r.Add(')');
        Console.WriteLine(new string(r.ToArray()));
    }
}

#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static int MaxElement<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        string S = sc.Str, T = sc.Str;
        var dp = Create(S.Length + 1, () => Create(T.Length+1, () => Create(201, () => int.MaxValue / 4)));
        dp[0][0][0] = 0;

        for (int i = 0; i <= S.Length; i++)
        {
            for (int j = 0; j <= T.Length; j++)
            {
                for (int k = 0; k < 200; k++)
                {
                    chmin(ref dp[i][j][k + 1], dp[i][j][k] + 1);
                }
                for (int k = 199; k >= 0; k--)
                {
                    chmin(ref dp[i][j][k], dp[i][j][k + 1] + 1);
                }
                for (int k = 0; k < 201; k++)
                {
                    if (i<S.Length&&j<T.Length&&S[i] == T[j])
                    {
                        int c = k;
                        if (S[i] == '(') c++;
                        else c--;
                        if (0 <= c && c < 201)
                            chmin(ref dp[i + 1][j + 1][c], dp[i][j][k] + 1);
                    }
                    if(i<S.Length)
                    {
                        int c = k;
                        if (S[i] == '(') c++;
                        else c--;
                        if (0 <= c && c < 201)
                            chmin(ref dp[i + 1][j][c], dp[i][j][k] + 1);
                    }
                    if(j<T.Length)
                    {
                        int c = k;
                        if (T[j] == '(') c++;
                        else c--;
                        if (0 <= c && c < 201)
                            chmin(ref dp[i][j + 1][c], dp[i][j][k] + 1);
                    }
                }
            }
        }
        var res = new List<char>();
        int s = S.Length, t = T.Length, l = 0;
        while (dp[s][t][l] != 0)
        {
            for(int j = -1; j < 2; j += 2)
            {
                int n = l + j;
                if (0 <= n && n < 201 && dp[s][t][n] + 1 == dp[s][t][l])
                {
                    l = n;
                    if (j == -1) res.Add('(');
                    else res.Add(')');
                    goto END;
                }
            }
            if (s>0&&t>0&&S[s - 1] == T[t - 1])
            {
                int n = l;
                if (S[s - 1] == '(') n--;
                else n++;
                if (0 <= n && n < 201 && dp[s - 1][t - 1][n] + 1 == dp[s][t][l])
                {
                    res.Add(S[s - 1]);
                    s--;t--;l = n;goto END;
                }
            }
            if (s > 0)
            {
                int n = l;
                if (S[s - 1] == '(') n--;
                else n++;
                if (0 <= n && n < 201 && dp[s - 1][t][n] + 1 == dp[s][t][l])
                {
                    res.Add(S[s - 1]);
                    s--; l = n; goto END;
                }
            }
            if (t > 0)
            {
                int n = l;
                if (T[t - 1] == '(') n--;
                else n++;
                if (0 <= n && n < 201 && dp[s][t-1][n] + 1 == dp[s][t][l])
                {
                    res.Add(T[t - 1]);
                    t--; l = n; goto END;
                }
            }
        END:;
        }
        res.Reverse();
        Console.WriteLine(new string(res.ToArray()));
    }
}

#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static int MaxElement<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


using System;
namespace CF
{
    public class Intercal
    {
        public static void Main()
        {
            Console.WriteLine("INTERCAL");
        }
    }
}


using System;
 class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("C#");
        }
    }


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Globalization;

class Program
{
    private static int[] GetCounts(int[] l, int max)
    {
        int[] count = new int[max + 1];
        for (int i = 0; i < n; i++) count[l[i]]++;
        return count;
    }

    private static Dictionary<int, int[]> distsCache = new Dictionary<int, int[]>();
    private static int[] GetDists(int vv)
    {
        if (distsCache.ContainsKey(vv))
            return distsCache[vv];

        int[] l = new int[n];

        List<int> buf = new List<int>() { vv };
        l[vv] = 1;
        int p = 0;
        while (p < buf.Count)
        {
            int v = buf[p++];
            foreach (var child in g[v])
                if (l[child] == 0)
                {
                    l[child] = l[v] + 1;
                    buf.Add(child);
                    if (buf.Count == n)
                    {
                        for (int i = 0; i < n; i++) l[i]--;
                        distsCache.Add(vv, l);
                        return l;
                    }
                }
        }

        for (int i = 0; i < n; i++) l[i]--;
        distsCache.Add(vv, l);

        return l;
    }

    private static double Try(int v)
    {
        var l = GetDists(v);
        int max = l.Max();

        int[] countByL = new int[max + 1];
        for (int i = 0; i < n; i++) countByL[l[i]]++;

        double ans = 0;

        double[] qq = new double[n];
        int[] id = new int[n];
        int nextId = 1;
        List<int> vv = new List<int>();

        for (int i = 0; i <= max; i++)
        {
            double p1 = 1 / (1.0 * n);
            if (countByL[i] == 1)
            {
                ans += p1;
                continue;
            }

            double[] q = new double[n];
            bool[] used = new bool[n];
            vv.Clear();

            for (int j = 0; j < n; j++)
                if (l[j] == i)
                {
                    double delta = 1 / (1.0 * (n * g[j].Count));
                    foreach (var ch in g[j])
                    {
                        q[ch] += delta;
                        if (!used[ch])
                        {
                            used[ch] = true;
                            vv.Add(ch);
                        }
                    }
                }

            double p2 = q.Max();

            double p3 = 0;
            for (int j = 0; j < n; j++)
            {
                nextId++;
                var l2 = GetDists(j);

                double qSum = 0;
                for (int ii = 0; ii < vv.Count; ii++)
                {
                    int vertex = vv[ii];
                    if (id[l2[vertex]] != nextId || q[vertex] > qq[l2[vertex]])
                    {
                        if (id[l2[vertex]] == nextId)
                            qSum -= qq[l2[vertex]];
                        else
                            id[l2[vertex]] = nextId;

                        qSum += q[vertex];
                        qq[l2[vertex]] = q[vertex];
                    }
                }

                p3 = Math.Max(qSum, p3);
            }

            ans += Math.Max(Math.Max(p1, p2), p3);
        }

        return ans;
    }

    private static int n;
    private static List<int>[] g;
    static void Main(string[] args)
    {
        n = ReadInt();
        int m = ReadInt();
        g = ReadGraph(n, m);

        double best = 0;
        for (int i = 0; i < n; i++)
        {
            best = Math.Max(best, Try(i));
            if (best + 1e-7 > 1) break;
        }

        Console.Write(DoubleToString(best));
    }

    private static int Mod = 1000000007;
    private static List<int>[] ReadGraph(int n, int m)
    {
        List<int>[] g = new List<int>[n];
        for (int i = 0; i < n; i++) g[i] = new List<int>();
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt() - 1;
            int b = ReadInt() - 1;

            g[a].Add(b);
            g[b].Add(a);
        }

        return g;
    }

    private static int[,] ReadGraphAsMatrix(int n, int m)
    {
        int[,] matrix = new int[n + 1, n + 1];
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt();
            int b = ReadInt();
            matrix[a, b] = matrix[b, a] = 1;
        }

        return matrix;
    }

    private static void Sort(ref int a, ref int b)
    {
        if (a > b) Swap(ref a, ref b);
    }

    private static void Swap(ref int a, ref int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    private const int BufferSize = 1 << 16;
    private static StreamReader consoleReader;
    private static MemoryStream testData;

    private static int ReadInt()
    {
        int ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static ulong ReadULong()
    {
        ulong ans = 0;
        int chr;
        do
        {
            chr = consoleReader.Read();
            if (chr == -1)
                return 0;
        } while (chr < '0' || chr > '9');

        ans = (uint)(chr - '0');
        while (true)
        {
            chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans;
            ans = ans * 10 + (uint)(chr - '0');
        }
    }

    private static long ReadLong()
    {
        long ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static int[] ReadIntArray(int n)
    {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadInt();
        return ans;
    }

    private static long[] ReadLongArray(int n)
    {
        long[] ans = new long[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadLong();
        return ans;
    }

    private static char[] ReadString()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        List<char> s = new List<char>();
        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s.ToArray();
    }

    private static char[] ReadString(int n)
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        char[] s = new char[n];
        int pos = 0;
        do
        {
            s[pos++] = (char)ans;
            if (pos == n) break;
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s;
    }

    private static char ReadLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'))
                return (char)ans;
        }
    }
    private static char ReadNonLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')))
                return (char)ans;
        }
    }

    private static char ReadDigit()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans >= '0' && ans <= '9')
                return (char)ans;
        }
    }

    private static int ReadDigitInt()
    {
        return ReadDigit() - (int)'0';
    }

    private static char ReadAnyChar()
    {
        return (char)consoleReader.Read();
    }

    private static string DoubleToString(double x)
    {
        return x.ToString(CultureInfo.InvariantCulture);
    }

    private static double DoubleFromString(string x)
    {
        return double.Parse(x, CultureInfo.InvariantCulture);
    }

    static Program()
    {
        //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        consoleReader = new StreamReader(Console.OpenStandardInput(BufferSize), Encoding.ASCII, false, BufferSize);
    }

    private static void PushTestData(string data)
    {
#if !ONLINE_JUDGE
        if (testData == null)
        {
            testData = new MemoryStream();
            consoleReader = new StreamReader(testData);
        }

        var pos = testData.Position;
        var bytes = Encoding.UTF8.GetBytes(data);
        testData.Write(bytes, 0, bytes.Length);
        testData.Flush();
        testData.Position = pos;
#endif
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Globalization;

class Program
{
    private static int[] GetCounts(int[] l, int max)
    {
        int[] count = new int[max + 1];
        for (int i = 0; i < n; i++) count[l[i]]++;
        return count;
    }

    private static Dictionary<int, int[]> distsCache = new Dictionary<int, int[]>();
    private static int[] GetDists(int vv)
    {
        if (distsCache.ContainsKey(vv))
            return distsCache[vv];

        int[] l = new int[n];

        List<int> buf = new List<int>() { vv };
        l[vv] = 1;
        int p = 0;
        while (p < buf.Count)
        {
            int v = buf[p++];
            foreach (var child in g[v])
                if (l[child] == 0)
                {
                    l[child] = l[v] + 1;
                    buf.Add(child);
                    //if (buf.Count == n)
                        //return l;
                }
        }

        for (int i = 0; i < n; i++) l[i]--;

        distsCache.Add(vv, l);

        return l;
    }

    private static double D(int x)
    {
        return 1 / (1.0 * x);
    }

    private static double Try(int v)
    {
        var l = GetDists(v);
        int max = l.Max();
        int[] countByL = GetCounts(l, max);

        double ans = 0;

        double[] qq = new double[n];
        int[] id = new int[n];
        int nextId = 1;

        for (int i = 0; i <= max; i++)
        {
            double p1 = D(n);
            if (countByL[i] == 1)
            {
                ans += p1;
                continue;
            }

            double[] q = new double[n];
            bool[] used = new bool[n];
            List<int> vv = new List<int>();

            for (int j = 0; j < n; j++)
                if (l[j] == i)
                {
                    double delta = D(n) * D(g[j].Count);
                    foreach (var ch in g[j])
                    {
                        q[ch] += delta;
                        if (!used[ch])
                        {
                            used[ch] = true;
                            vv.Add(ch);
                        }
                    }
                }

            double p2 = q.Max();

            double p3 = 0;
            for (int j = 0; j < n; j++)
            {
                nextId++;
                var l2 = GetDists(j);

                double qSum = 0;
                for (int ii = 0; ii < vv.Count; ii++)
                {
                    int vertex = vv[ii];
                    if (id[l2[vertex]] != nextId || q[vertex] > qq[l2[vertex]])
                    {
                        if (id[l2[vertex]] == nextId)
                            qSum -= qq[l2[vertex]];
                        else
                            id[l2[vertex]] = nextId;

                        qSum += q[vertex];
                        qq[l2[vertex]] = q[vertex];
                    }
                }

                p3 = Math.Max(qSum, p3);
            }

            ans += Math.Max(Math.Max(p1, p2), p3);
        }

        return ans;
    }

    private static void Test1()
    {
        PushTestData(@"
3 3
1 2
1 3
2 3");
        Console.WriteLine("Expected: 0.8333333");
    }
    private static void Test2()
    {
        PushTestData(@"
5 4
1 2
3 1
5 1
1 4");
        Console.WriteLine("Expected: 1.000000");
    }
    private static void Test3()
    {
        PushTestData(@"
4 4
1 2
1 3
2 3
1 4");

        Console.WriteLine("Expected: 0.916666666667");

    }
    private static void Test4()
    {
        PushTestData(@"
5 5
1 2
2 3
3 4
4 5
1 5");
        Console.WriteLine("Expected: 0.90000000");
    }

    private static void Test5(int n = 400)
    {
        int m = n * (n - 1) / 2;
        var sb = new StringBuilder();
        sb.AppendLine(n + " " + m);
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++)
                sb.AppendLine(i + " " + j);
        Console.WriteLine("Expected: FULL");
        PushTestData(sb.ToString());
    }

    private static void Test6(int n = 400)
    {
        int m = n - 1;
        var sb = new StringBuilder();
        sb.AppendLine(n + " " + m);
        for (int i = 1; i < n; i++)
            sb.AppendLine(i + " " + (i + 1));
        Console.WriteLine("Expected: CHINE");
        PushTestData(sb.ToString());
    }
    private static void Test7(int n = 400)
    {
        int m = n - 1;
        var sb = new StringBuilder();
        sb.AppendLine(n + " " + m);
        for (int i = 1; i < n; i++)
            sb.AppendLine(i + " " + (i + 1));
        sb.AppendLine(1 + " " + n);
        Console.WriteLine("Expected: CIRCLE");
        PushTestData(sb.ToString());
    }
    private static void Test8(int n = 400)
    {
        int m = n - 1;
        var sb = new StringBuilder();
        sb.AppendLine(n + " " + m);
        for (int i = 2; i <= n; i++)
        {
            int prev = i - 4;
            if (prev < 0) prev = 0;
            sb.AppendLine((prev + 1) + " " + i);
        }

        Console.WriteLine("Expected: PLUS");
        var str = sb.ToString();
        PushTestData(str);
    }

    private static Random rnd = new Random();
    private static void Test9(int n = 400)
    {
        int m = rnd.Next(n - 1, n * (n - 1) / 2);
        bool[,] mm = new bool[n, n];
        for (int i = 1; i < n; i++)
        {
            mm[i, i - 1] = true;
            mm[i - 1, i] = true;
        }

        for (int i = n - 1; i < m; i++)
        {
            int a = rnd.Next(n);
            int b = rnd.Next(n);
            mm[a, b] = true;
            mm[b, a] = true;
        }

        m = 0;
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                if (mm[i, j])
                    m++;

        var sb = new StringBuilder();
        sb.AppendLine(n + " " + m);
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                if (mm[i, j])
                    sb.AppendLine((i + 1) + " " + (j + 1));

        Console.WriteLine("Expected: RANDOM");
        var str = sb.ToString();
        PushTestData(str);
    }

    private static int n;
    private static List<int>[] g;
    static void Main(string[] args)
    {
        //Test9();
        //Test2();
        //Test3();
        //Test4();

        var dt1 = DateTime.Now;
        n = ReadInt();
        int m = ReadInt();
        g = ReadGraph(n, m);

        double best = 0;
        for (int i = 0; i < n; i++)
        {
            best = Math.Max(best, Try(i));
            //Console.WriteLine(i + " " + best);
            //if (best + 1e-7 > 1) break;
        }

        var dt2 = DateTime.Now;
        //Console.WriteLine("Total Time = " + (dt2 - dt1).TotalMilliseconds);
        Console.Write(DoubleToString(best));
    }

    private static int Mod = 1000000007;
    private static List<int>[] ReadGraph(int n, int m)
    {
        List<int>[] g = new List<int>[n];
        for (int i = 0; i < n; i++) g[i] = new List<int>();
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt() - 1;
            int b = ReadInt() - 1;

            g[a].Add(b);
            g[b].Add(a);
        }

        return g;
    }

    private static int[,] ReadGraphAsMatrix(int n, int m)
    {
        int[,] matrix = new int[n + 1, n + 1];
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt();
            int b = ReadInt();
            matrix[a, b] = matrix[b, a] = 1;
        }

        return matrix;
    }

    private static void Sort(ref int a, ref int b)
    {
        if (a > b) Swap(ref a, ref b);
    }

    private static void Swap(ref int a, ref int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    private const int BufferSize = 1 << 16;
    private static StreamReader consoleReader;
    private static MemoryStream testData;

    private static int ReadInt()
    {
        int ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static ulong ReadULong()
    {
        ulong ans = 0;
        int chr;
        do
        {
            chr = consoleReader.Read();
            if (chr == -1)
                return 0;
        } while (chr < '0' || chr > '9');

        ans = (uint)(chr - '0');
        while (true)
        {
            chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans;
            ans = ans * 10 + (uint)(chr - '0');
        }
    }

    private static long ReadLong()
    {
        long ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static int[] ReadIntArray(int n)
    {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadInt();
        return ans;
    }

    private static long[] ReadLongArray(int n)
    {
        long[] ans = new long[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadLong();
        return ans;
    }

    private static char[] ReadString()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        List<char> s = new List<char>();
        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s.ToArray();
    }

    private static char[] ReadString(int n)
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        char[] s = new char[n];
        int pos = 0;
        do
        {
            s[pos++] = (char)ans;
            if (pos == n) break;
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s;
    }

    private static char ReadLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'))
                return (char)ans;
        }
    }
    private static char ReadNonLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')))
                return (char)ans;
        }
    }

    private static char ReadDigit()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans >= '0' && ans <= '9')
                return (char)ans;
        }
    }

    private static int ReadDigitInt()
    {
        return ReadDigit() - (int)'0';
    }

    private static char ReadAnyChar()
    {
        return (char)consoleReader.Read();
    }

    private static string DoubleToString(double x)
    {
        return x.ToString(CultureInfo.InvariantCulture);
    }

    private static double DoubleFromString(string x)
    {
        return double.Parse(x, CultureInfo.InvariantCulture);
    }

    static Program()
    {
        //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        consoleReader = new StreamReader(Console.OpenStandardInput(BufferSize), Encoding.ASCII, false, BufferSize);
    }

    private static void PushTestData(string data)
    {
#if !ONLINE_JUDGE
        if (testData == null)
        {
            testData = new MemoryStream();
            consoleReader = new StreamReader(testData);
        }

        var pos = testData.Position;
        var bytes = Encoding.UTF8.GetBytes(data);
        testData.Write(bytes, 0, bytes.Length);
        testData.Flush();
        testData.Position = pos;
#endif
    }
}


using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using System.Numerics;
using Point = System.Numerics.Complex;
using Number = System.Int64;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var M = sc.Long();
            for (long i = 1; i < 100020; i++)
            {
                L[i] = (i * i * i);
            }
            //Debug.WriteLine(L.AsJoinedString());
            var max = Get(M);
            var ans = dfs(M, max);
            IO.Printer.Out.WriteLine("{0} {1}", max, ans);
        }

        long[] L = new long[100020];
        public long dfs(long X, long k)
        {
            if (k == 0)
            {
                if (X == 0) return 0;
                else return -1000000000000000;
            }
            if(X==0)
            {
                if (k > 0) return -1000000000000000;
            }
            var p = L.UpperBound(X) - 1;
            var ans = dfs(X - L[p], k - 1) + L[p];
            if (p > 0) ans = Math.Max(ans, dfs(L[p] - 1, k));
            return ans;
        }
        public long Get(long X)
        {
            var ans = 0L;
            var sum = 0L;
            for (long i = 1; i <= 100000; i++)
            {
                var v = i * i * i;
                var V = (i + 1) * (i + 1) * (i + 1);
                var k = (V - 1 - sum) / v;
                k = Math.Min(k, (X - sum) / v);
                //Debug.WriteLine(k);
                ans += k;
                sum += k * v;
            }
            Debug.WriteLine(sum);
            return ans;
        }
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }

    }
}
#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer : StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion
#region BinarySearch for Number[]
static public partial class Algorithm
{
    static public int LowerBound(this Number[] arr, Number v)
    {
        int l = 0, h = arr.Length - 1;
        while (l <= h)
        {
            int m = ((h + l) >> 1);
            if (arr[m] < v) l = m + 1;
            else h = m - 1;
        }
        return l;
    }
    static public int UpperBound(this Number[] a, Number v)
    {
        int l = 0, h = a.Length - 1;
        while (l <= h)
        {
            int m = ((h + l) >> 1);
            if (a[m] <= v) l = m + 1;
            else h = m - 1;
        }
        return l;
    }

}
#endregion


using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Threading;

namespace B
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
            int tc = 1;
            //tc = int.Parse(Console.ReadLine());
            while (tc-- > 0)
            {
                solve();
            }
        }

        // write your code in solve function
        static void solve()
        {
            int n = int.Parse(Console.ReadLine());
            int[] ratings = new int[]{1200, 1400, 1600, 1900, 2100, 2300, 2400, 2600, 3000};

            for (int i=0; i<ratings.Length; i++) {
                if (n <= ratings[i]) {
                    Console.WriteLine(ratings[i]);
                    return;
                }
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Threading;

namespace B
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
            int tc = 1;
            //tc = int.Parse(Console.ReadLine());
            while (tc-- > 0)
            {
                solve();
            }
        }

        // write your code in solve function
        static void solve()
        {
            int n = int.Parse(Console.ReadLine());
            int[] ratings = new int[]{1200, 1400, 1600, 1900, 2100, 2300, 2400, 2600, 3000};

            for (int i=0; i<ratings.Length; i++) {
                if (n < ratings[i]) {
                    Console.WriteLine(ratings[i]);
                    return;
                }
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class Example {
    public static void Main(String[] args) {
        int[] ratings = new int[9];
        ratings[0] = 1200;
        ratings[1] = 1400;
        ratings[2] = 1600;
        ratings[3] = 1900;
        ratings[4] = 2100;
        ratings[5] = 2300;
        ratings[6] = 2400;
        ratings[7] = 2600;
        ratings[8] = 3000;
        int t = int.Parse (Console.ReadLine ());
        // for (int r = -50; r < 3300; r += 50) {
        // System.out.print((t = r) + " : ");
        if (t < ratings[0]) {
            t = ratings[0];
        } else {
            for (int i = 0; i < 8; ++i) {
                if (ratings[i] <= t && t < ratings[i + 1]) {
                    t = ratings[i + 1];
                    break;
                }
            }
        }
        Console.WriteLine("" + t);
        // }
    }
}