using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;

namespace Codeforces.TaskD
{
    public class Task
    {
        private int d;
        private Point[] points;

        private double Distance(double l, int i)
        {
            // tg a1 = x/y
            // tg (alpha - a1) = (z-x)/y => z = x + y tg (alpha - a1)
            // tg (a+b) = (tg a + tg b)/(1 - tg a tg b)
            // z = x + y (tg alpha - x/y) / (1 + (x/y) tg alpha) = x + y (y tg alpha - x) / (y + x tg alpha) =
            // (xy + x2 tg + y2 tg - xy) / (y + x tg) = tg alpha (x2 + y2) / (y + x tg alpha)

            // tg a2 = -x/y
            // tg (alpha + a2) = (z-x)/y

            var p = points[i];
            var x = p.X - l;
            var y = p.Y;
            var tg = p.TgAlpha;

            if (x < 0)
            {
                var maxAlpha = Math.PI/2 - Math.Abs(Math.Atan2(x, y));
                if (p.Alpha >= maxAlpha) return d;
            }

            var denom = y + x*tg;
            if (denom == 0) return d;
            var z = l + Math.Abs(tg*(x*x + y*y)/denom);
            return Math.Min(d, z);
        }

        void Solve()
        {
            int n, l, r;
            Input.Next(out n, out l, out r);
            d = r - l;

            points = new Point[n];
            for (var i = 0; i < n; i++)
            {
                points[i] = new Point();
                Input.Next(out points[i].X, out points[i].Y, out points[i].Angle);
                points[i].X -= l;
                points[i].Alpha = points[i].Angle * Math.PI / 180;
                points[i].TgAlpha = Math.Tan(points[i].Alpha);
            }

            var dp = new double[1 << n << 1];
            for (var j = 0; j < 1<<n<<1; j++)
                for (var i=0;i<n;i++)
                    if ((j & (1 << i)) == 0)
                        dp[j | (1 << i)] = Math.Max(dp[j | (1 << i)], Distance(dp[j], i));
            Console.Write(dp[(1<<n)-1].ToString("f9", CultureInfo.InvariantCulture));
        }

        public static void Main()
        {
            var task = new Task();
            #if DEBUG
            task.Solve();
            #else
            try
            {
                task.Solve();
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex);
            }
            #endif
        }
    }

    sealed class Point
    {
        public int X;
        public int Y;
        public int Angle;
        public double Alpha;
        public double TgAlpha;
    }
}

namespace Codeforces
{
    public class Input
    {
        private static string _line;

        public static bool Next()
        {
            _line = Console.ReadLine();
            return _line != null;
        }

        public static bool Next(out long a)
        {
            var ok = Next();
            a = ok ? long.Parse(_line) : 0;
            return ok;
        }

        public static bool Next(out long a, out long b)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
            }
            else
            {
                a = b = 0;
            }

            return ok;
        }

        public static bool Next(out long a, out long b, out long c)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
            }
            else
            {
                a = b = c = 0;
            }
            return ok;
        }

        public static bool Next(out long a, out long b, out long c, out long d)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
            }
            else
            {
                a = b = c = d = 0;
            }
            return ok;
        }

        public static bool Next(out long a, out long b, out long c, out long d, out long e)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
                e = array[4];
            }
            else
            {
                a = b = c = d = e = 0;
            }
            return ok;
        }

        public static bool Next(out int a)
        {
            var ok = Next();
            a = ok ? int.Parse(_line) : 0;
            return ok;
        }

        public static bool Next(out int a, out int b)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(int.Parse).ToArray();
                a = array[0];
                b = array[1];
            }
            else
            {
                a = b = 0;
            }

            return ok;
        }

        public static bool Next(out int a, out int b, out int c)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(int.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
            }
            else
            {
                a = b = c = 0;
            }
            return ok;
        }

        public static bool Next(out int a, out int b, out int c, out int d)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(int.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
            }
            else
            {
                a = b = c = d = 0;
            }
            return ok;
        }

        public static bool Next(out int a, out int b, out int c, out int d, out int e)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(int.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
                e = array[4];
            }
            else
            {
                a = b = c = d = e = 0;
            }
            return ok;
        }

        public static bool Next(out int a, out int b, out int c, out int d, out int e, out int f)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(int.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
                e = array[4];
                f = array[5];
            }
            else
            {
                a = b = c = d = e = f = 0;
            }
            return ok;
        }

        public static IEnumerable<long> ArrayLong()
        {
            return !Next() ? new List<long>() : _line.Split().Select(long.Parse);
        }

        public static IEnumerable<int> ArrayInt()
        {
            return !Next() ? new List<int>() : _line.Split().Select(int.Parse);
        }

        public static bool Next(out string value)
        {
            value = string.Empty;
            if (!Next()) return false;
            value = _line;
            return true;
        }
    }

    public class DisjointSet
    {
        private readonly int[] _parent;
        private readonly int[] _rank;
        public int Count { get; private set; }

        public DisjointSet(int count, int initialize = 0)
        {
            Count = count;
            _parent = new int[Count];
            _rank = new int[Count];
            for (var i = 0; i < initialize; i++) _parent[i] = i;
        }

        private DisjointSet(int count, int[] parent, int[] rank)
        {
            Count = count;
            _parent = parent;
            _rank = rank;
        }

        public void Add(int v)
        {
            _parent[v] = v;
            _rank[v] = 0;
        }

        public int Find_Recursive(int v)
        {
            if (_parent[v] == v) return v;
            return _parent[v] = Find(_parent[v]);
        }

        public int Find(int v)
        {
            if (_parent[v] == v) return v;
            var last = v;
            while (_parent[last] != last) last = _parent[last];
            while (_parent[v] != v)
            {
                var t = _parent[v];
                _parent[v] = last;
                v = t;
            }
            return last;
        }

        public int this[int v]
        {
            get { return Find(v); }
            set { Union(v, value); }
        }

        public void Union(int a, int b)
        {
            a = Find(a);
            b = Find(b);
            if (a == b) return;
            if (_rank[a] < _rank[b])
            {
                var t = _rank[a];
                _rank[a] = _rank[b];
                _rank[b] = t;
            }
            _parent[b] = a;
            if (_rank[a] == _rank[b]) _rank[a]++;
        }

        public int GetSetCount()
        {
            var result = 0;
            for (var i = 0; i < Count; i++)
            {
                if (_parent[i] == i) result++;
            }
            return result;
        }

        public DisjointSet Clone()
        {
            var rank = new int[Count];
            _rank.CopyTo(rank, 0);
            var parent = new int[Count];
            _parent.CopyTo(parent, 0);
            return new DisjointSet(Count, parent, rank);
        }

        public override string ToString()
        {
            return string.Join(",", _parent.Take(50));
        }
    }

    public class Matrix
    {
        public static Matrix Create(int i, int j)
        {
            var m = new Matrix(i, j);
            return m;
        }

        public static Matrix Create(int i)
        {
            var m = new Matrix(i, i);
            return m;
        }

        public long Modulo { get; set; }

        private readonly int _width;
        private readonly int _height;
        private readonly long[,] _data;
        public int Width { get { return _width; } }
        public int Height { get { return _height; } }

        private Matrix(int i, int j)
        {
            Modulo = 1000000000000000000L;
            _width = j;
            _height = i;
            _data = new long[_height, _width];
        }

        public static Matrix operator *(Matrix m1, Matrix m2)
        {
            if (m1.Width != m2.Height) throw new InvalidDataException("m1.Width != m2.Height");
            var m = Create(m2.Width, m1.Height);
            m.Modulo = m1.Modulo;
            for (var i = 0; i < m2.Width; i++)
                for (var j = 0; j < m1.Height; j++)
                {
                    for (var k = 0; k < m1.Width; k++)
                        m[j, i] += (m1[j, k] * m2[k, i]) % m1.Modulo;
                    m[j, i] %= m1.Modulo;
                }
            return m;
        }

        public static Matrix operator +(Matrix m1, Matrix m2)
        {
            var m = m1.Clone();
            for (var i = 0; i < m2.Width; i++)
                for (var j = 0; j < m1.Height; j++)
                    m[j, i] = (m[j, i] + m2[j, i]) % m1.Modulo;
            return m;
        }

        public static Matrix operator -(Matrix m1, Matrix m2)
        {
            var m = m1.Clone();
            for (var i = 0; i < m2.Width; i++)
                for (var j = 0; j < m1.Height; j++)
                    m[j, i] = (m[j, i] - m2[j, i]) % m1.Modulo;
            return m;
        }

        public static Matrix operator *(Matrix m1, long l)
        {
            var m = m1.Clone();
            for (var i = 0; i < m1.Width; i++)
                for (var j = 0; j < m1.Height; j++)
                    m[j, i] = (m[j, i] * l) % m.Modulo;
            return m;
        }

        public static Matrix operator *(long l, Matrix m1)
        {
            return m1 * l;
        }

        public static Matrix operator +(Matrix m1, long l)
        {
            var m = m1.Clone();
            for (var i = 0; i < m1.Width; i++)
                m[i, i] = (m[i, i] + l) % m.Modulo;
            return m;
        }

        public static Matrix operator +(long l, Matrix m1)
        {
            return m1 + l;
        }

        public static Matrix operator -(Matrix m1, long l)
        {
            return m1 + (-l);
        }

        public static Matrix operator -(long l, Matrix m1)
        {
            var m = m1.Clone() * -1;
            return m + l;
        }

        public Matrix BinPower(long l)
        {
            var n = 1;
            var m = Clone();
            var result = new Matrix(m.Height, m.Width) + 1;
            result.Modulo = m.Modulo;
            while (l != 0)
            {
                var i = l & ~(l - 1);
                l -= i;
                while (n < i)
                {
                    m = m * m;
                    n <<= 1;
                }
                result *= m;
            }
            return result;
        }

        public void Fill(long l)
        {
            l %= Modulo;
            for (var i = 0; i < _height; i++)
                for (var j = 0; j < _width; j++)
                    _data[i, j] = l;
        }

        public Matrix Clone()
        {
            var m = new Matrix(_width, _height);
            Array.Copy(_data, m._data, _data.Length);
            m.Modulo = Modulo;
            return m;
        }

        public long this[int i, int j]
        {
            get { return _data[i, j]; }
            set { _data[i, j] = value % Modulo; }
        }
    }

    public class RedBlackTree<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private readonly List<Node> _items;
        private Node _root;
        private readonly IComparer<TKey> _comparer;

        public RedBlackTree(int capacity = 10)
        {
            _items = new List<Node>(capacity);
            _comparer = Comparer<TKey>.Default;
        }

        private Node _search(TKey key)
        {
            var node = _root;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return node;
                node = i > 0 ? node.Right : node.Left;
            }
            return null;
        }

        /// <summary>
        /// Returns lower or equal key
        /// </summary>
        public TKey Lower(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node good = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return key;
                if (i > 0)
                {
                    good = node;
                    node = node.Right;
                }
                else
                    node = node.Left;
            }
            return good == null ? notFound : good.Key;
        }

        /// <summary>
        /// Returns higher or equal key
        /// </summary>
        public TKey Higher(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node good = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return key;
                if (i < 0)
                {
                    good = node;
                    node = node.Left;
                }
                else
                    node = node.Right;
            }
            return good == null ? notFound : good.Key;
        }

        /// <summary>
        /// Returns minimum region, which encloses given key
        /// </summary>
        public Tuple<TKey, TKey> Bounds(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node lower = null;
            Node higher = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return new Tuple<TKey, TKey>(key, key);
                if (i < 0)
                {
                    higher = node;
                    node = node.Left;
                }
                else
                {
                    lower = node;
                    node = node.Right;
                }
            }
            return new Tuple<TKey, TKey>(lower == null ? notFound : lower.Key, higher == null ? notFound : higher.Key);
        }

        public void Add(TKey key, TValue value)
        {
            var node = new Node { Key = key, Value = value, Red = true };
            _items.Add(node);
            if (_root == null)
            {
                _root = node;
                _root.Red = false;
                return;
            }
            var x = _root;
            Node y = null;
            while (x != null)
            {
                y = x;
                x = _comparer.Compare(key, x.Key) > 0 ? x.Right : x.Left;
            }
            node.Parent = y;
            if (y == null) _root = node;
            else if (_comparer.Compare(key, y.Key) > 0) y.Right = node;
            else y.Left = node;
            InsertFixup(node);
        }

        private void InsertFixup(Node node)
        {
            while (true)
            {
                var parent = node.Parent;
                if (parent == null || !parent.Red || parent.Parent == null) break;
                var grand = parent.Parent;

                if (parent == grand.Left)
                {
                    var uncle = grand.Right;
                    if (uncle != null && uncle.Red) /* parent and uncle both red: we could swap colors of them with grand */
                    {
                        parent.Red = false;
                        uncle.Red = false;
                        grand.Red = true;
                        node = grand; /* and continue fixing tree for grand */
                    }
                    else if (node == parent.Right) /* we rotate around the parent */
                    {
                        node = parent;
                        RotateLeft(node);
                    }
                    else /* rotate around grand and switch colors of grand and parent */
                    {
                        parent.Red = false;
                        grand.Red = true;
                        RotateRight(grand);
                        if (grand == _root) _root = parent;
                        break; /* and finish since tree is fixed */
                    }
                }
                else
                {
                    if (_root.Parent != null) Debugger.Break();

                    var uncle = grand.Left;
                    if (uncle != null && uncle.Red) /* parent and uncle both red: we could swap colors of them with grand */
                    {
                        parent.Red = false;
                        uncle.Red = false;
                        grand.Red = true;
                        node = grand; /* and continue fixing tree for grand */
                    }
                    else if (node == parent.Left) /* we rotate around the parent */
                    {
                        node = parent;
                        RotateRight(node);
                    }
                    else /* rotate around grand and switch colors of grand and parent */
                    {
                        parent.Red = false;
                        grand.Red = true;
                        RotateLeft(grand);
                        if (grand == _root) _root = parent;
                        break; /* and finish since tree is fixed */
                    }
                }
            }
            _root.Red = false;
        }

        private void RotateLeft(Node node)
        {
            if (node.Right == null)
                throw new NotSupportedException("Cannot rotate left: right node is missing");
            var parent = node.Parent;
            var right = node.Right;
            right.Parent = parent;
            if (parent != null)
            {
                if (parent.Left == node) parent.Left = right;
                else parent.Right = right;
            }
            node.Right = right.Left;
            if (node.Right != null)
                node.Right.Parent = node;
            right.Left = node;
            node.Parent = right;
        }

        private void RotateRight(Node node)
        {
            if (node.Left == null)
                throw new NotSupportedException("Cannot rotate right: left node is missing");
            var parent = node.Parent;
            var left = node.Left;
            left.Parent = parent;
            if (parent != null)
            {
                if (parent.Left == node) parent.Left = left;
                else parent.Right = left;
            }
            node.Left = left.Right;
            if (node.Left != null)
                node.Left.Parent = node;
            left.Right = node;
            node.Parent = left;
        }

        public void Remove(TKey key)
        {
            var node = _search(key);
            if (node == null) return;

            var deleted = node.Left == null || node.Right == null ? node : Next(node);
            var child = deleted.Left ?? deleted.Right;
            if (child != null)
                child.Parent = deleted.Parent;
            if (deleted.Parent == null) /* root */
                _root = child;
            else if (deleted == deleted.Parent.Left)
                deleted.Parent.Left = child;
            else
                deleted.Parent.Right = child;
            if (node != deleted)
            {
                node.Key = deleted.Key;
                node.Value = deleted.Value;
            }

            if (!deleted.Red)
            {
                DeleteFixup(child, deleted.Parent);
            }
        }

        private void DeleteFixup(Node node, Node parent)
        {
            while (parent != null && (node == null || !node.Red))
            {
                if (node == parent.Left)
                {
                    var brother = parent.Right;
                    if (brother.Red)
                    {
                        brother.Red = false;
                        parent.Red = true;
                        RotateLeft(parent);
                        brother = parent.Right;
                    }
                    if ((brother.Left == null || !brother.Left.Red) && (brother.Right == null || !brother.Right.Red))
                    {
                        node = parent.Red ? _root : parent;
                        brother.Red = true;
                        parent.Red = false;
                    }
                    else
                    {
                        if (brother.Right == null || !brother.Right.Red)
                        {
                            if (brother.Left != null)
                                brother.Left.Red = false;
                            brother.Red = true;
                            RotateRight(brother);
                            brother = parent.Right;
                        }
                        if (!brother.Right.Red) Debugger.Break();
                        brother.Red = parent.Red;
                        parent.Red = false;
                        if (brother.Right != null)
                            brother.Right.Red = false;
                        RotateLeft(parent);
                        node = _root;
                    }
                }
                else
                {
                    var brother = parent.Left;
                    if (brother.Red)
                    {
                        brother.Red = false;
                        parent.Red = true;
                        RotateRight(parent);
                        brother = parent.Left;
                    }
                    if ((brother.Right == null || !brother.Right.Red) && (brother.Left == null || !brother.Left.Red))
                    {
                        node = parent.Red ? _root : parent;
                        brother.Red = true;
                        parent.Red = false;
                    }
                    else
                    {
                        if (brother.Left == null || !brother.Left.Red)
                        {
                            if (brother.Right != null)
                                brother.Right.Red = false;
                            brother.Red = true;
                            RotateLeft(brother);
                            brother = parent.Left;
                        }
                        brother.Red = parent.Red;
                        parent.Red = false;
                        if (brother.Left != null)
                            brother.Left.Red = false;
                        RotateRight(parent);
                        node = _root;
                    }
                }
                parent = node.Parent;
            }

            node.Red = false;
        }

        public TValue this[TKey key]
        {
            get
            {
                var node = _search(key);
                return node == null ? default(TValue) : node.Value;
            }
            set
            {
                var node = _search(key);
                if (node == null) Add(key, value);
                else node.Value = value;
            }
        }

        public bool Check()
        {
            int count;
            return _root == null || _root.Check(out count);
        }

        private Node Minimum(Node node)
        {
            var result = node;
            while (result.Left != null) result = result.Left;
            return result;
        }

        private Node Maximum(Node node)
        {
            var result = node;
            while (result.Right != null) result = result.Right;
            return result;
        }

        private Node Next(Node node)
        {
            Node result;
            if (node.Right != null)
            {
                result = Minimum(node.Right);
            }
            else
            {
                while (node.Parent != null && node.Parent.Right == node)
                    node = node.Parent;
                result = node.Parent;
            }
            return result;
        }

        private Node Previous(Node node)
        {
            Node result;
            if (node.Left != null)
            {
                result = Maximum(node.Left);
            }
            else
            {
                while (node.Parent != null && node.Parent.Left == node)
                    node = node.Parent;
                result = node.Parent;
            }
            return result;
        }

        public void Print()
        {
            var node = Minimum(_root);
            while (node != null)
            {
                Console.Write(node.Red ? '*' : ' ');
                Console.Write(node.Key);
                Console.Write('\t');
                node = Next(node);
            }
        }

        #region Nested classes

        [DebuggerDisplay("{ToString()}")]
        private sealed class Node
        {
            public TKey Key;
            public TValue Value;
            public bool Red;

            public Node Parent;
            public Node Left;
            public Node Right;

            public bool Check(out int count)
            {
                count = 0;
                if (Red)
                {
                    if (Left != null && Left.Red) return false;
                    if (Right != null && Right.Red) return false;
                }
                var left = 0;
                var right = 0;
                if (Left != null && !Left.Check(out left)) return false;
                if (Right != null && !Right.Check(out right)) return false;
                count = left + (Red ? 0 : 1);
                if (left != right)
                {
                    ;
                }
                return left == right;
            }

            public override string ToString()
            {
                return ToShortString(2);
            }

            private string ToShortString(int depth = 0)
            {
                return depth == 0
                    ? string.Format("{0}{1}", Red ? "*" : "", Key)
                    : string.Format("({1}<{0}>{2})", ToShortString(), Left == null ? "null" : Left.ToShortString(depth - 1), Right == null ? "null" : Right.ToShortString(depth - 1));
            }
        }

        #endregion

        #region IEnumerable

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }

    public class RedBlackTreeSimple<TKey>
    {
        private readonly List<Node> _items;
        private Node _root;
        private readonly IComparer<TKey> _comparer;

        public RedBlackTreeSimple(int capacity = 10)
        {
            _items = new List<Node>(capacity);
            _comparer = Comparer<TKey>.Default;
        }

        private Node _search(TKey key)
        {
            var node = _root;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return node;
                node = i > 0 ? node.Right : node.Left;
            }
            return null;
        }

        /// <summary>
        /// Returns lower or equal key
        /// </summary>
        public TKey Lower(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node good = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return key;
                if (i > 0)
                {
                    good = node;
                    node = node.Right;
                }
                else
                    node = node.Left;
            }
            return good == null ? notFound : good.Key;
        }

        /// <summary>
        /// Returns higher or equal key
        /// </summary>
        public TKey Higher(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node good = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return key;
                if (i < 0)
                {
                    good = node;
                    node = node.Left;
                }
                else
                    node = node.Right;
            }
            return good == null ? notFound : good.Key;
        }

        /// <summary>
        /// Returns minimum region, which encloses given key
        /// </summary>
        public Tuple<TKey, TKey> Bounds(TKey key, TKey notFound = default(TKey))
        {
            var node = _root;
            Node lower = null;
            Node higher = null;
            while (node != null)
            {
                var i = _comparer.Compare(key, node.Key);
                if (i == 0) return new Tuple<TKey, TKey>(key, key);
                if (i < 0)
                {
                    higher = node;
                    node = node.Left;
                }
                else
                {
                    lower = node;
                    node = node.Right;
                }
            }
            return new Tuple<TKey, TKey>(lower == null ? notFound : lower.Key, higher == null ? notFound : higher.Key);
        }

        public void Add(TKey key)
        {
            var node = new Node(key);
            _items.Add(node);
            if (_root == null)
            {
                _root = node;
                _root.Red = false;
                return;
            }
            var x = _root;
            Node y = null;
            while (x != null)
            {
                y = x;
                x = _comparer.Compare(key, x.Key) > 0 ? x.Right : x.Left;
            }
            node.Parent = y;
            if (y == null) _root = node;
            else if (_comparer.Compare(key, y.Key) > 0) y.Right = node;
            else y.Left = node;
            InsertFixup(node);
        }

        private void InsertFixup(Node node)
        {
            while (true)
            {
                var parent = node.Parent;
                if (parent == null || !parent.Red || parent.Parent == null) break;
                var grand = parent.Parent;

                if (parent == grand.Left)
                {
                    var uncle = grand.Right;
                    if (uncle != null && uncle.Red) /* parent and uncle both red: we could swap colors of them with grand */
                    {
                        parent.Red = false;
                        uncle.Red = false;
                        grand.Red = true;
                        node = grand; /* and continue fixing tree for grand */
                    }
                    else if (node == parent.Right) /* we rotate around the parent */
                    {
                        node = parent;
                        RotateLeft(node);
                    }
                    else /* rotate around grand and switch colors of grand and parent */
                    {
                        parent.Red = false;
                        grand.Red = true;
                        RotateRight(grand);
                        if (grand == _root) _root = parent;
                        break; /* and finish since tree is fixed */
                    }
                }
                else
                {
                    if (_root.Parent != null) Debugger.Break();

                    var uncle = grand.Left;
                    if (uncle != null && uncle.Red) /* parent and uncle both red: we could swap colors of them with grand */
                    {
                        parent.Red = false;
                        uncle.Red = false;
                        grand.Red = true;
                        node = grand; /* and continue fixing tree for grand */
                    }
                    else if (node == parent.Left) /* we rotate around the parent */
                    {
                        node = parent;
                        RotateRight(node);
                    }
                    else /* rotate around grand and switch colors of grand and parent */
                    {
                        parent.Red = false;
                        grand.Red = true;
                        RotateLeft(grand);
                        if (grand == _root) _root = parent;
                        break; /* and finish since tree is fixed */
                    }
                }
            }
            _root.Red = false;
        }

        private void RotateLeft(Node node)
        {
            if (node.Right == null)
                throw new NotSupportedException("Cannot rotate left: right node is missing");
            var parent = node.Parent;
            var right = node.Right;
            right.Parent = parent;
            if (parent != null)
            {
                if (parent.Left == node) parent.Left = right;
                else parent.Right = right;
            }
            node.Right = right.Left;
            if (node.Right != null)
                node.Right.Parent = node;
            right.Left = node;
            node.Parent = right;
        }

        private void RotateRight(Node node)
        {
            if (node.Left == null)
                throw new NotSupportedException("Cannot rotate right: left node is missing");
            var parent = node.Parent;
            var left = node.Left;
            left.Parent = parent;
            if (parent != null)
            {
                if (parent.Left == node) parent.Left = left;
                else parent.Right = left;
            }
            node.Left = left.Right;
            if (node.Left != null)
                node.Left.Parent = node;
            left.Right = node;
            node.Parent = left;
        }

        public void Remove(TKey key)
        {
            var node = _search(key);
            if (node == null) return;

            var deleted = node.Left == null || node.Right == null ? node : Next(node);
            var child = deleted.Left ?? deleted.Right;
            if (child != null)
                child.Parent = deleted.Parent;
            if (deleted.Parent == null) /* root */
                _root = child;
            else if (deleted == deleted.Parent.Left)
                deleted.Parent.Left = child;
            else
                deleted.Parent.Right = child;
            if (node != deleted)
            {
                node.Key = deleted.Key;
            }

            if (!deleted.Red)
            {
                DeleteFixup(child, deleted.Parent);
            }
        }

        private void DeleteFixup(Node node, Node parent)
        {
            while (parent != null && (node == null || !node.Red))
            {
                if (node == parent.Left)
                {
                    var brother = parent.Right;
                    if (brother.Red)
                    {
                        brother.Red = false;
                        parent.Red = true;
                        RotateLeft(parent);
                        brother = parent.Right;
                    }
                    if ((brother.Left == null || !brother.Left.Red) && (brother.Right == null || !brother.Right.Red))
                    {
                        node = parent.Red ? _root : parent;
                        brother.Red = true;
                        parent.Red = false;
                    }
                    else
                    {
                        if (brother.Right == null || !brother.Right.Red)
                        {
                            if (brother.Left != null)
                                brother.Left.Red = false;
                            brother.Red = true;
                            RotateRight(brother);
                            brother = parent.Right;
                        }
                        if (!brother.Right.Red) Debugger.Break();
                        brother.Red = parent.Red;
                        parent.Red = false;
                        if (brother.Right != null)
                            brother.Right.Red = false;
                        RotateLeft(parent);
                        node = _root;
                    }
                }
                else
                {
                    var brother = parent.Left;
                    if (brother.Red)
                    {
                        brother.Red = false;
                        parent.Red = true;
                        RotateRight(parent);
                        brother = parent.Left;
                    }
                    if ((brother.Right == null || !brother.Right.Red) && (brother.Left == null || !brother.Left.Red))
                    {
                        node = parent.Red ? _root : parent;
                        brother.Red = true;
                        parent.Red = false;
                    }
                    else
                    {
                        if (brother.Left == null || !brother.Left.Red)
                        {
                            if (brother.Right != null)
                                brother.Right.Red = false;
                            brother.Red = true;
                            RotateLeft(brother);
                            brother = parent.Left;
                        }
                        brother.Red = parent.Red;
                        parent.Red = false;
                        if (brother.Left != null)
                            brother.Left.Red = false;
                        RotateRight(parent);
                        node = _root;
                    }
                }
                parent = node.Parent;
            }

            node.Red = false;
        }

        private Node Minimum(Node node)
        {
            var result = node;
            while (result.Left != null) result = result.Left;
            return result;
        }

        private Node Maximum(Node node)
        {
            var result = node;
            while (result.Right != null) result = result.Right;
            return result;
        }

        private Node Next(Node node)
        {
            Node result;
            if (node.Right != null)
            {
                result = Minimum(node.Right);
            }
            else
            {
                while (node.Parent != null && node.Parent.Right == node)
                    node = node.Parent;
                result = node.Parent;
            }
            return result;
        }

        private Node Previous(Node node)
        {
            Node result;
            if (node.Left != null)
            {
                result = Maximum(node.Left);
            }
            else
            {
                while (node.Parent != null && node.Parent.Left == node)
                    node = node.Parent;
                result = node.Parent;
            }
            return result;
        }

        public void Print()
        {
            var node = Minimum(_root);
            while (node != null)
            {
                Console.Write(node.Red ? '*' : ' ');
                Console.Write(node.Key);
                Console.Write('\t');
                node = Next(node);
            }
        }

        #region Nested classes

        private sealed class Node
        {
            public Node(TKey key)
            {
                Key = key;
            }

            public TKey Key;
            public bool Red = true;

            public Node Parent;
            public Node Left;
            public Node Right;
        }

        #endregion
    }

    /// <summary>
    /// Fenwick tree for summary on the array
    /// </summary>
    public class FenwickSum
    {
        public readonly int Size;
        private readonly int[] _items;
        public FenwickSum(int size)
        {
            Size = size;
            _items = new int[Size];
        }

        public FenwickSum(IList<int> items)
            : this(items.Count)
        {
            for (var i = 0; i < Size; i++)
                Increase(i, items[i]);
        }

        private int Sum(int r)
        {
            if (r < 0) return 0;
            if (r >= Size) r = Size - 1;
            var result = 0;
            for (; r >= 0; r = (r & (r + 1)) - 1)
                result += _items[r];
            return result;
        }

        private int Sum(int l, int r)
        {
            return Sum(r) - Sum(l - 1);
        }

        public int this[int r]
        {
            get { return Sum(r); }
        }

        public int this[int l, int r]
        {
            get { return Sum(l, r); }
        }

        public void Increase(int i, int delta)
        {
            for (; i < Size; i = i | (i + 1))
                _items[i] += delta;
        }
    }

    /// <summary>
    /// Prime numbers
    /// </summary>
    public class Primes
    {
        /// <summary>
        /// Returns prime numbers in O(n)
        /// Returns lowet divisors as well
        /// Memory O(n)
        /// </summary>
        public static void ImprovedSieveOfEratosthenes(int n, out int[] lp, out List<int> pr)
        {
            lp = new int[n];
            pr = new List<int>();
            for (var i = 2; i < n; i++)
            {
                if (lp[i] == 0)
                {
                    lp[i] = i;
                    pr.Add(i);
                }
                foreach (var prJ in pr)
                {
                    var prIj = i * prJ;
                    if (prJ <= lp[i] && prIj <= n - 1)
                    {
                        lp[prIj] = prJ;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Returns prime numbers in O(n*n)
        /// </summary>
        public static void SieveOfEratosthenes(int n, out List<int> pr)
        {
            var m = 2 * n / 5;
            pr = new List<int> { 2 };
            var f = new bool[n + 1];
            for (var i = 3; i <= m; i += 2)
                if (!f[i])
                    for (long j = (long)i * i; j <= n; j += i)
                        f[j] = true;
            for (var i = 3; i <= n; i += 2)
                if (!f[i])
                    pr.Add(i);
        }

        /// <summary>
        /// Returns array of inverted prime numbers map in O(n*n)
        /// </summary>
        public static void SieveOfEratosthenes(int n, out bool[] isPrime)
        {
            var m = 2 * n / 5;
            var f = new bool[n + 1];
            for (var i = 3; i <= m; i += 2)
                if (!f[i])
                    for (long j = (long)i * i; j <= n; j += i)
                        f[j] = true;
            isPrime = f;
        }

        /// <summary>
        /// Greatest common divisor
        /// </summary>
        public static int Gcd(int x, int y)
        {
            while (y != 0)
            {
                var c = y;
                y = x % y;
                x = c;
            }
            return x;
        }

        /// <summary>
        /// Greatest common divisor
        /// </summary>
        public static long Gcd(long x, long y)
        {
            while (y != 0)
            {
                var c = y;
                y = x % y;
                x = c;
            }
            return x;
        }

        /// <summary>
        /// Greatest common divisor
        /// </summary>
        public static BigInteger Gcd(BigInteger x, BigInteger y)
        {
            while (y != 0)
            {
                var c = y;
                y = x % y;
                x = c;
            }
            return x;
        }

        /// <summary>
        /// Returns all divisors of n in O(√n)
        /// </summary>
        public static IEnumerable<long> GetDivisors(long n)
        {
            long r;
            while (true)
            {
                var x = Math.DivRem(n, 2, out r);
                if (r != 0) break;
                n = x;
                yield return 2;
            }
            var i = 3;
            while (i <= Math.Sqrt(n))
            {
                var x = Math.DivRem(n, i, out r);
                if (r == 0)
                {
                    n = x;
                    yield return i;
                }
                else i += 2;
            }
            if (n != 1) yield return n;
        }
    }

    /// <summary>
    /// Graph matching algorithms
    /// </summary>
    public class GraphMatching
    {
        #region Kuhn algorithm

        /// <summary>
        /// Kuhn algorithm for finding maximal matching
        /// in bipartite graph
        /// Vertexes are numerated from zero: 0, 1, 2, ... n-1
        /// Return array of matchings
        /// </summary>
        public static int[] Kuhn(List<int>[] g, int leftSize, int rightSize)
        {
            Debug.Assert(g.Count() == leftSize);

            var matching = new int[leftSize];
            for (var i = 0; i < rightSize; i++)
                matching[i] = -1;
            var used = new bool[leftSize];

            for (var v = 0; v < leftSize; v++)
            {
                Array.Clear(used, 0, leftSize);
                _kuhn_dfs(v, g, matching, used);
            }

            return matching;
        }

        private static bool _kuhn_dfs(int v, List<int>[] g, int[] matching, bool[] used)
        {
            if (used[v]) return false;
            used[v] = true;
            for (var i = 0; i < g[v].Count; i++)
            {
                var to = g[v][i];
                if (matching[to] == -1 || _kuhn_dfs(matching[to], g, matching, used))
                {
                    matching[to] = v;
                    return true;
                }
            }
            return false;
        }

        #endregion
    }
}


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

namespace Codeforces
{
    internal class Program
    {
        private const string Test = "F1";

        private static void Solve()
        {
            var inpit = ReadIntArray();
            var a0 = inpit[0];
            var a1 = inpit[1];
            var n = inpit[2];
            var res = a0;
            if(n == 1)
                Console.WriteLine(a1);
            else
            {
                for (int i = 2; i <= n; i++)
                {
                    res = a0 + a1;
                    a0 = a1;
                    a1 = res;
                }
                Console.WriteLine(res);
            }
        }

        private static void Main()
        {
            if (Debugger.IsAttached)
            {
                //Console.SetIn(new StreamReader(String.Format(@"..\..\..\..\Tests\{0}.in", Test)));
            }

            Solve();

            if (Debugger.IsAttached)
            {
                Console.In.Close();
                Console.SetIn(new StreamReader(Console.OpenStandardInput()));
                Console.ReadLine();
            }
        }

        #region Reader

        private static string Read()
        {
            return Console.ReadLine();
        }

        private static string[] ReadArray()
        {
            return Console.ReadLine().Split(' ');
        }

        private static List<int> ReadIntArray()
        {
            var input = Console.ReadLine().Split(' ').Select(Int32.Parse).ToList();
            return input;
        }

        private static int ReadInt()
        {
            return Int32.Parse(Console.ReadLine());
        }

        private static long ReadLong()
        {
            return long.Parse(Console.ReadLine());
        }

        private static int ReadNextInt(string[] input, int index)
        {
            return Int32.Parse(input[index]);
        }

        #endregion
    }
}


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

namespace INTERCALC
{
    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 void Main(string[] args)
        {
            int n = Next();

            var nn = new int[n];
            for (int i = 0; i < n; i++)
            {
                nn[i] = Next();
            }

            writer.WriteLine(nn.Max() - nn[n - 1]);
            writer.Flush();
        }

        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;

namespace CodeForces
{
    class Program
    {
        struct Matrix
        {
            public long A1, A2, A3, A4;
            const long BMod = 10000000;

            public static long MulMod(long a, long b, long mod)
            {
                if (a == 0 || b == 0)
                    return 0;
                else if (long.MaxValue / b > a)
                    return (a * b) % mod;
                else
                {
                    long j0 = a / BMod;
                    long j1 = a % BMod;
                    long k0 = b / BMod;
                    long k1 = b % BMod;
                    long r = (((j0 * k1 + j1 * k0) % (mod / BMod)) * BMod + j1 * k1) % mod;
                    return r;
                }
            }

            public static Matrix MulMod(Matrix m1, Matrix m2, long mod)
            {
                Matrix result = new Matrix();
                result.A1 = (MulMod(m1.A1, m2.A1, mod) + MulMod(m1.A2, m2.A3, mod)) % mod;
                result.A2 = (MulMod(m1.A1, m2.A2, mod) + MulMod(m1.A2, m2.A4, mod)) % mod;
                result.A3 = (MulMod(m1.A3, m2.A1, mod) + MulMod(m1.A4, m2.A3, mod)) % mod;
                result.A4 = (MulMod(m1.A3, m2.A2, mod) + MulMod(m1.A4, m2.A4, mod)) % mod;
                return result;
            }

            public void Mod(long mod)
            {
                A1 %= mod; A2 %= mod; A3 %= mod; A4 %= mod;
            }

            public static Matrix PowerMod(long power, Matrix m, long mod)
            {
                Matrix modLast = m, result = new Matrix();

                while (power != 0)
                {
                    if ((power & 1) == 1)
                    {
                        if (result.A1 == 0)
                            result = modLast;
                        else
                            result = Matrix.MulMod(result, modLast, mod);
                    }

                    modLast = Matrix.MulMod(modLast, modLast, mod);
                    power >>= 1;
                }

                return result;
            }
        }

        struct Result
        {
            public long Index, Value;
            public int SIndex;
        }

        static void Main(string[] args)
        {
            long[] steps = new long[] { 60, 300, 1500, 15000, 150000, 1500000, 15000000, 150000000, 1500000000, 15000000000, 150000000000, 1500000000000, 15000000000000, 150000000000000, 1500000000000000, 15000000000000000 };
            long[] mods = new long[] { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000 };

            long n = Convert.ToInt64(Console.ReadLine());
            int index = 0;
            long modValue = n % mods[index];

            Queue<Result> queue = new Queue<Result>();
            long[] fs = new long[60]; fs[1] = 1;

            for (int i = 2; i < fs.Length; i++)
            {
                fs[i] = (fs[i - 1] + fs[i - 2]) % mods[index];
                if (fs[i] == modValue)
                    queue.Enqueue(new Result { Index = i, Value = fs[i], SIndex = index });
            }

            List<Result> result = new List<Result>();

            while (queue.Count > 0)
            {
                Result current = queue.Dequeue();

                if (current.Value == n && current.SIndex == 12)
                {
                    result.Add(current);
                    continue;
                }
                else if (current.SIndex > 12)
                    continue;

                for (int i = 0; i * steps[current.SIndex] < steps[current.SIndex + 1]; i++)
                {
                    long nIndex = i * steps[current.SIndex] + current.Index;
                    long value = Cal(nIndex, mods[current.SIndex + 1]);

                    if (value == n % mods[current.SIndex + 1])
                        queue.Enqueue(new Result { Index = nIndex, SIndex = current.SIndex + 1, Value = value });
                }
            }

            if (result.Count == 0)
                Console.WriteLine(-1);
            else
            {
                long sIndex = result.Select(x => x.Index).Min();
                Console.WriteLine(sIndex);
            }
        }

        static long Cal(long index, long mod)
        {
            Matrix m = new Matrix { A1 = 1, A2 = 1, A3 = 1, A4 = 0 };
            Matrix power = Matrix.PowerMod(index, m, mod);
            return (long)power.A2;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace CodeForces
{
    class Program
    {
        struct Matrix
        {
            public long A1, A2, A3, A4;
            const long BMod = 10000000;

            public static long MulMod(long a, long b, long mod)
            {
                if (a == 0 || b == 0)
                    return 0;
                else if (long.MaxValue / b > a)
                    return (a * b) % mod;
                else
                {
                    long j0 = a / BMod;
                    long j1 = a % BMod;
                    long k0 = b / BMod;
                    long k1 = b % BMod;
                    long r = (((j0 * k1 + j1 * k0) % (mod / BMod)) * BMod + j1 * k1) % mod;
                    return r;
                }
            }

            public static Matrix MulMod(Matrix m1, Matrix m2, long mod)
            {
                Matrix result = new Matrix();
                result.A1 = (MulMod(m1.A1, m2.A1, mod) + MulMod(m1.A2, m2.A3, mod)) % mod;
                result.A2 = (MulMod(m1.A1, m2.A2, mod) + MulMod(m1.A2, m2.A4, mod)) % mod;
                result.A3 = (MulMod(m1.A3, m2.A1, mod) + MulMod(m1.A4, m2.A3, mod)) % mod;
                result.A4 = (MulMod(m1.A3, m2.A2, mod) + MulMod(m1.A4, m2.A4, mod)) % mod;
                return result;
            }

            public void Mod(long mod)
            {
                A1 %= mod; A2 %= mod; A3 %= mod; A4 %= mod;
            }

            public static Matrix PowerMod(long power, Matrix m, long mod)
            {
                Matrix modLast = m, result = new Matrix();

                while (power != 0)
                {
                    if ((power & 1) == 1)
                    {
                        if (result.A1 == 0)
                            result = modLast;
                        else
                            result = Matrix.MulMod(result, modLast, mod);
                    }

                    modLast = Matrix.MulMod(modLast, modLast, mod);
                    power >>= 1;
                }

                return result;
            }
        }

        struct Result
        {
            public long Index, Value;
            public int SIndex;
        }

        static void Main(string[] args)
        {
            long[] steps = new long[] { 60, 300, 1500, 15000, 150000, 1500000, 15000000, 150000000, 1500000000, 15000000000, 150000000000, 1500000000000, 15000000000000, 150000000000000, 1500000000000000, 15000000000000000 };
            long[] mods = new long[] { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000 };

            long n = Convert.ToInt64(Console.ReadLine());

            if (n == 1)
            {
                Console.WriteLine(1);
                return;
            }

            int index = 0;
            long modValue = n % mods[index];

            Queue<Result> queue = new Queue<Result>();
            long[] fs = new long[60]; fs[1] = 1;

            for (int i = 2; i < fs.Length; i++)
            {
                fs[i] = (fs[i - 1] + fs[i - 2]) % mods[index];
                if (fs[i] == modValue)
                    queue.Enqueue(new Result { Index = i, Value = fs[i], SIndex = index });
            }

            List<Result> result = new List<Result>();

            while (queue.Count > 0)
            {
                Result current = queue.Dequeue();

                if (current.Value == n && current.SIndex == 12)
                {
                    result.Add(current);
                    continue;
                }
                else if (current.SIndex > 12)
                    continue;

                for (int i = 0; i * steps[current.SIndex] < steps[current.SIndex + 1]; i++)
                {
                    long nIndex = i * steps[current.SIndex] + current.Index;
                    long value = Cal(nIndex, mods[current.SIndex + 1]);

                    if (value == n % mods[current.SIndex + 1])
                        queue.Enqueue(new Result { Index = nIndex, SIndex = current.SIndex + 1, Value = value });
                }
            }

            if (result.Count == 0)
                Console.WriteLine(-1);
            else
            {
                long sIndex = result.Select(x => x.Index).Min();
                Console.WriteLine(sIndex);
            }
        }

        static long Cal(long index, long mod)
        {
            Matrix m = new Matrix { A1 = 1, A2 = 1, A3 = 1, A4 = 0 };
            Matrix power = Matrix.PowerMod(index, m, mod);
            return (long)power.A2;
        }
    }
}


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

namespace Hack_it
{
    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 void Main(string[] args)
        {
            BigInteger sum = 0;
            BigInteger count = 1;
            int i = 1;
            for (; i < 20; i++)
            {
                count *= 10;
            }
            for (int j = 1; j < 10; j++)
            {
                sum += count*j*i;
            }
            sum += 1;
            count *= 10;

            BigInteger a = BigInteger.Parse(reader.ReadLine());

            BigInteger d = sum%a;
            if (d != 0)
            {
                d = a - d;
            }

            writer.WriteLine("{0} {1}", d + 1, count + d);
            writer.Flush();
        }
    }
}


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

namespace Hack_it
{
    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 void Main(string[] args)
        {
            BigInteger sum = 0;
            BigInteger count = 1;
            int i = 1;
            for (; i <= 20; i++)
            {
                count *= 10;
            }

            for (int j = 1; j < 10; j++)
            {
                sum += count*j*i;
            }
            sum += 1;

            BigInteger a = BigInteger.Parse(reader.ReadLine());

            BigInteger d = sum%a;
            if (d != 0)
            {
                d = a - d;
            }

            writer.WriteLine("{0} {1}", d + 1, count + d);
            writer.Flush();
        }
    }
}


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

namespace ProgrammingContest.Codeforces.Round59
{
    class E
    {
        int[][] dx = new int[][]{
            new int[]{2,4,6},
            new int[]{1,3,5,7},
            new int[]{0,2,4,6,8},
            new int[]{1,3,5,7},
            new int[]{2,4,6}
        };

        char[][] cs = new char[5][];
        int[,] id = new int[10, 10];
        List<int> chk = new List<int>();

        bool ok(int x, int y)
        {
            return 0 <= y && y < 5 && dx[y].Contains(x);
        }

        void proc(int x, int y, int dx, int dy)
        {
            int hash = 0;
            for (; ok(x, y); x += dx, y += dy)
            {
                hash |= 1 << id[x, y];
                chk.Add(hash);
            }
        }

        E()
        {
            for (int i = 0; i < 5; i++)
                cs[i] = Console.ReadLine().ToCharArray();

            int state = 0;
            for(int y = 0, idx = 0; y < 5; y++)
                for (int i = 0; i < dx[y].Length; i++)
                {
                    int x = dx[y][i];
                    id[x,y] = idx++;
                    if (cs[y][x] == 'O')
                        state |= 1 << id[x, y];
                }

            for (int y = 0; y < 5; y++)
                for (int i = 0; i < dx[y].Length; i++)
                {
                    int x = dx[y][i];
                    proc(x, y, 2, 0);
                    proc(x, y, 1, 1);
                    proc(x, y, -1, 1);
                }

            bool[] win = new bool[1<<19];
            for (int i = 1; i < 1 << 19; i++)
            {
                foreach (int hash in chk)
                {
                    if ((i & hash) == hash && !win[i ^ hash])
                    {
                        win[i] = true;
                        break;
                    }
                }
            }

            Console.WriteLine(win[state] ? "Karlsson" : "Lillebror");
        }

        public static void Main()
        {
            new E();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace Codeforces.TaskE
{
    public class Task
    {
        public static void Main()
        {
            var task = new Task();
            task.Solve();
        }

        private const long Mod = 1000000007L;
        private const long Max = 102L;
        private long n, m, k;
        private long[,,,] Ways;
        private long[][] C;

        void Solve()
        {
            Input.Next(out n, out m, out k);

            C = new long[Max][];
            C[0] = new long[1];
            C[0][0] = 1;
            for (var i = 1; i < Max; i++)
            {
                C[i] = new long[i + 1];
                C[i][0] = 1; C[i][i] = 1;
                for (var j = 1; j < i; j++)
                    C[i][j] = C[i - 1][j - 1] + C[i - 1][j] % Mod;
            }

            n /= 2;
            Ways = new long[n + 2, n + 2, n + 2, Max];
            Ways[0, 1, 0, 1] = 1;

            var result = 0L;
            for (var maxValue = 0; maxValue <= n && maxValue < m; maxValue++)
                for (var holes = 0; holes <= n; holes++)
                    for (var total = 0; total <= n; total++)
                        for (var ways = 0; ways <= k; ways++)
                        {
                            var prevWays = Ways[maxValue, holes, total, ways];
                            if (prevWays == 0) continue;
                            if (maxValue > 0)
                            {
                                result += (prevWays * (m - maxValue)) % Mod;
                                result %= Mod;
                            }

                            for (var newCountOfMaxValues = 1; newCountOfMaxValues <= n - total; newCountOfMaxValues++)
                            {
                                var newWays = ways*C[holes + newCountOfMaxValues - 1][newCountOfMaxValues];
                                if (newWays <= k)
                                {
                                    Ways[maxValue + 1, newCountOfMaxValues, total + newCountOfMaxValues, newWays] += prevWays;
                                    Ways[maxValue + 1, newCountOfMaxValues, total + newCountOfMaxValues, newWays] %= Mod;
                                }
                            }
                        }
            Console.WriteLine(result);
        }
    }

    #region Input

    public class Input
    {
        private static string _line;

        public static bool Next()
        {
            _line = Console.ReadLine();
            return !string.IsNullOrEmpty(_line);
        }

        public static bool Next(out long a)
        {
            var ok = Next();
            a = ok ? long.Parse(_line) : 0;
            return ok;
        }

        public static bool Next(out long a, out long b)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
            }
            else
            {
                a = b = 0;
            }

            return ok;
        }

        public static bool Next(out long a, out long b, out long c)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
            }
            else
            {
                a = b = c = 0;
            }
            return ok;
        }

        public static bool Next(out long a, out long b, out long c, out long d)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
            }
            else
            {
                a = b = c = d = 0;
            }
            return ok;
        }

        public static bool Next(out long a, out long b, out long c, out long d, out long e)
        {
            var ok = Next();
            if (ok)
            {
                var array = _line.Split(' ').Select(long.Parse).ToArray();
                a = array[0];
                b = array[1];
                c = array[2];
                d = array[3];
                e = array[4];
            }
            else
            {
                a = b = c = d = e = 0;
            }
            return ok;
        }

        public static List<long> Numbers()
        {
            Next();
            return _line.Split(' ').Select(long.Parse).ToList();
        }
    }

    #endregion

}


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

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){

		long[][] nCr = new long[21][];
		for(int i=0;i<21;i++){
			nCr[i] = new long[21];
		}

		nCr[0][0] = 1;
		for(int i=1;i<21;i++){
			nCr[i][0] = 1;
			for(int j=1;j<21;j++){
				nCr[i][j] = nCr[i-1][j] + nCr[i-1][j-1];
			}
		}
		long[] dp = new long[N+1];
		dp[0] = 1;
		int[] cnt = new int[10];
		for(int i=0;i<N;i++) cnt[S[i] - '0']++;
//Console.WriteLine("ok");

		for(int v=9;v>=0;v--){
			if(cnt[v] == 0) continue;
//Console.WriteLine(String.Join(" ",  dp));
			long[] ndp = new long[N+1];
			for(int l=0;l<=N;l++){
				if(dp[l] == 0) continue;
				for(int c = 1; c <= cnt[v]; c++){
					int m = l + 1;
					if(v == 0) m--;
					ndp[l + c] += dp[l] * nCr[m - 1 + c][c];
				}
			}
			dp = ndp;
//Console.WriteLine("ndpp:{0}",String.Join(" ",  dp));
		}

		Console.WriteLine(dp.Sum());
	}
	int N;
	String S;
	public Sol(){
		S = rs();
		N = S.Length;
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}


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

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    public void Solve()
    {
        int ans = 0;
        foreach (char c in ReadToken())
            if (char.IsLetter(c))
            {
                if (char.IsUpper(c))
                    ans += c - 'A' + 1;
                else
                    ans -= c - 'a' + 1;
            }

        Write(ans);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
            new Solver().Solve();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


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

namespace cfgr14
{
    class Program
    {
        static void Main(string[] args)
        {
           Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
            if (File.Exists("input.txt"))
            {
                Console.SetIn(new StreamReader("input.txt"));
            }
            solve_cfgr14E();
            Console.Out.Flush();
        }

        public static long[] fact = new long [405];
        public static long[] inv = new long [405];
        public static long[,] choose = new long [405, 405];
        public static long[] pow2 = new long [405];
        public static long n;
        public static long mod;
        /*
        Editorial:

        */
        public static void solve_cfgr14E()
        {
            long[] nm = Array.ConvertAll(Console.ReadLine().Split(), long.Parse);
            n = nm[0];
            mod = nm[1];
            precompute();
            long[,] dp = new long[405, 405];
            dp[0, 0] = 1;
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    for (int k = 1; i + k <= n; k++)
                    {
                        dp[i + k + 1, j + k] += (dp[i, j] * pow2[k - 1]) % mod * choose[j + k, k];
                        dp[i + k + 1, j + k] %= mod;
                    }
                }
            }

            long ans = 0;
            for (int i = 0; i <= n; i++)
            {
                ans = (ans + dp[n + 1, i]) % mod;
            }
            Console.WriteLine(ans);
        }

        public static void precompute()
        {
            fact[0] = 1;
            inv[0] = 1;
            for (int i = 1; i <= n; i++)
            {
                fact[i] = (fact[i - 1] * i) % mod;
                inv[i] = binExp(fact[i], mod - 2);
            }

            for (int i = 0; i <= n; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    choose[i, j] = ((fact[i] * inv[j]) % mod * inv[i - j]) % mod;
                }
            }

            for (int i = 0; i <= n; i++)
            {
                pow2[i] = binExp(2, i);
            }
        }

        public static long binExp(long a, long exp)
        {
            if (exp == 0)
            {
                return 1;
            }
            long tmp = binExp(a, exp / 2);
            tmp = (tmp * tmp) % mod;
            if (exp % 2 == 1)
            {
                tmp *= a;
            }
            return tmp % mod;
        }

        public static void solve_cfgr14C()
        {
            int t = Convert.ToInt32(Console.ReadLine());
            while(t-- > 0)
            {
                int[] nmx = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                int n = nmx[0];
                int m = nmx[1];
                int x = nmx[2];
                int[] h = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                Array.Sort(h);
                int[] cnt = new int[m];
                for (int i = 0; i < n; i++)
                {
                    cnt[i % m] += h[i];
                }
                int min = int.MaxValue;
                int max = int.MinValue;
                bool ok = true;
                for (int i = 0; i < m; i++)
                {
                    min = Math.Min(min, cnt[i]);
                    max = Math.Max(max, cnt[i]);
                    if (max - min > x)
                    {
                        ok = false;
                        break;
                    }
                }
                if (ok)
                {
                    Console.WriteLine("YES");
                    for (int i = 0; i < n; i++)
                    {
                        Console.Write("{0} ", (i % m) + 1);
                    }
                }
                else
                {
                    Console.Write("NO");
                }
                Console.WriteLine();
            }
        }

        public static void solve_cfgr14B()
        {
            int t = Convert.ToInt32(Console.ReadLine());
            while(t-- > 0)
            {
                int n = Convert.ToInt32(Console.ReadLine());
                bool ok = false;
                if (n > 1 && (n & (n - 1)) == 0)
                {
                    ok = true;
                }
                else
                {
                    for (int i = 2; i * i <= 1000000000; i++)
                    {
                        if (i % 2 != 0)
                        {
                            if (n % (i * i) == 0)
                            {
                                int r = n / (i * i);
                                if (r > 1 && (r & (r - 1)) == 0)
                                {
                                    ok = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                Console.WriteLine(ok ? "YES" : "NO");
            }

        }

        public static void solve_cfgr14A()
        {
            int t = Convert.ToInt32(Console.ReadLine());
            while(t-- > 0)
            {
                int[] nx = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                int n = nx[0];
                int x = nx[1];
                int[] w = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                Array.Sort(w, (a, b) => b.CompareTo(a));
                int sum = 0;
                int posToChange = -1;
                for (int i = 0; i < n; i++)
                {
                    sum += w[i];
                    if (sum == x)
                    {
                        posToChange = i;
                    }
                }
                if (sum != x)
                {
                    Console.WriteLine("YES");
                    for (int i = 0; i < n; i++)
                    {
                        if (i == posToChange)
                        {
                            if (i + 1 < n)
                            {
                                int tmp = w[i];
                                w[i] = w[i + 1];
                                w[i + 1] = tmp;
                            }
                        }
                        Console.Write("{0} ", w[i]);
                    }
                }
                else
                {
                    Console.Write("NO");
                }
                Console.WriteLine();

            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using static System.Math;

namespace CompetitiveProgramming
{
	class Program
	{
		public static void Main()
		{
			var ints = Console.ReadLine().Split().Select(long.Parse).ToArray();

			var n = ints[0];
			var mod = ints[1];

			for (int i = 1; i < Inverses.Length; i++)
				Inverses[i] = ModularMultiplicativeInverse(i, mod);

			var cur = new long[,]
			{
				{0,0,0 },
				{0,0,0 },
				{0,0,2 },
				{4,0,0 },
			};

			for (var i = 0; i < n - 3; i++)
				cur = GetNext(cur, mod);

			long res = 0;

			for (int i = 0; i < cur.GetLength(0); i++)
				for (int j = 0; j < cur.GetLength(1); j++)
					res += cur[i, j];

			Console.WriteLine(res % mod);
		}

		private static readonly long[] Inverses = new long[500];

		public static long[,] GetNext(long[,] current, long mod)
		{
			var total = current.GetLength(0) - 1;
			var next = new long[total + 2, total + 1];

			for (int i = 0; i <= total; i++)
				for (int last = 0; last < total; last++)
				{
					var prev = current[i, last];
					if (prev == 0)
						continue;

					var dist = total + 1 - last;

					var nVal = prev * 2 * (i + 1) % mod * Inverses[dist] % mod;
					next[i + 1, last] = (next[i + 1, last] + nVal) % mod;

					if (last != total - 1)
					{
						var val = prev * Inverses[2] % mod * (dist - 1) % mod;
						next[i, total] = (next[i, total] + val) % mod;
					}
				}

			return next;
		}

		public static long ModularMultiplicativeInverse(long remainder, long mod)
		{
			if (mod == 1)
				return 0;

			var other = mod;
			long next = 0;
			long inverse = 1;

			while (remainder > 1)
			{
				(inverse, next) = (next, inverse - remainder / other * next);
				(remainder, other) = (other, remainder % other);
			}

			if (inverse < 0)
				inverse += mod;

			return inverse;
		}

		public static List<int[]> GetPermutations(int[] list)
		{
			int x = list.Length - 1;
			var result = new List<int[]>();
			GetPermutationsRec(list, result, 0, x);
			return result;
		}

		private static void GetPermutationsRec(int[] list, List<int[]> result, int k, int m)
		{
			if (k == m)
				result.Add(list.ToArray());
			else
				for (int i = k; i <= m; i++)
				{
					Swap(ref list[k], ref list[i]);
					GetPermutationsRec(list, result, k + 1, m);
					Swap(ref list[k], ref list[i]);
				}
		}

		private class Perm
		{
			public List<int> vals;
			public Perm missing;

			public Perm(int[] vals)
			{
				if (vals.Length == 0)
				{
					this.vals = new List<int>();
					return;
				}

				var isIn = new bool[15];
				var nl = new List<int>();
				var ms = new List<int>();
				foreach (var v in vals)
				{
					isIn[v] = true;
					if (isIn[v - 1] && isIn[v + 1])
					{
						ms.Add(v);
					}
					else
						nl.Add(v);
				}

				ms.Sort();

				this.missing = new Perm(ms.ToArray());

				this.vals = nl;
			}

			public override bool Equals(object obj)
			{
				var mType = obj as Perm;
				if (mType == null)
					return false;

				return mType.vals.SequenceEqual(vals);
			}

			public override int GetHashCode()
			{
				int seed = vals.Count;
				const int lul = (int)(0x9e3779b9 - int.MaxValue / 2);

				foreach (var v in vals)
				{
					seed ^= v + lul + (seed << 6) + (seed >> 2);
				}

				return seed;
			}

			public override string ToString()
			{
				return '{' + string.Join(' ', vals) + '}';
			}
		}

		private static void NewMethod1()
		{
			var cases = int.Parse(Console.ReadLine());
			var sols = new int[cases];

			for (int @case = 0; @case < cases; @case++)
			{
				var ints = Console.ReadLine().Split().Select(int.Parse).ToArray();
				var n = ints[0];
				var l = ints[1];
				var r = ints[2];

				var socks = Console.ReadLine().Split().Select(int.Parse).ToArray();
				var colorCount = socks.Max() + 1;

				var colorCountsL = new int[colorCount];
				var colorCountsR = new int[colorCount];

				for (int i = 0; i < l; i++)
					colorCountsL[socks[i]]++;

				for (int i = l; i < n; i++)
					colorCountsR[socks[i]]++;

				if (l < r)
				{
					Swap(ref colorCountsL, ref colorCountsR);
					Swap(ref l, ref r);
				}

				var diff = (l - r) / 2;

				for (int i = 0; i < colorCount; i++)
				{
					var min = Min(colorCountsL[i], colorCountsR[i]);
					colorCountsL[i] -= min;
					colorCountsR[i] -= min;

					var changedColor = Min(colorCountsL[i] / 2, diff);
					{
						colorCountsL[i] -= 2 * changedColor;
						diff -= changedColor;
					}
				}

				sols[@case] = (l - r) / 2 + (colorCountsR.Sum() + colorCountsL.Sum()) / 2;

				// staramy sie wyrownac liczbe kolorow miedzy prawymi a lewymi
				// wiemy ze lewych jest wiecej rowno prawych
			}

			sols.ToList().ForEach(x => Console.WriteLine(x));
		}

		public static void Swap<T>(ref T a, ref T b)
		{
			T t = a;
			a = b;
			b = t;
		}

		private static void NewMethod()
		{
			var sqrt = (int)Math.Sqrt(int.MaxValue / 2);
			var squares = Enumerable.Range(1, sqrt).Select(x => x * x).ToHashSet();

			var cases = int.Parse(Console.ReadLine());
			var sols = new bool[cases];

			for (int @case = 0; @case < cases; @case++)
			{
				var n = int.Parse(Console.ReadLine());
				sols[@case] = (n % 2 == 0 && squares.Contains(n / 2)) || (n % 4 == 0 && squares.Contains(n / 4));
			}

			sols.ToList().ForEach(x => Console.WriteLine(x ? "YES" : "NO"));
		}

		private static void RunCaseA()
		{
			var ints = Console.ReadLine().Split().Select(int.Parse).ToArray();
			var n = ints[0];
			var k = ints[1];

			var vals = Console.ReadLine().Split().Select(int.Parse).ToArray();
			var total = vals.Sum();
			if (k != total)
			{

				var sol = new List<int>();
				var current = 0;

				for (int i = 0; i < vals.Length; i++)
				{
					if (current + vals[i] == k)
					{
						current += vals[i] + vals[i + 1];
						sol.Add(vals[i + 1]);
						sol.Add(vals[i]);
						i += 1;
					}
					else
					{
						sol.Add(vals[i]);
						current += vals[i];
					}
				}
			}
		}

		static void PrintSol(int[] sol)
		{
			if (sol == null)
				Console.WriteLine("NO");
			else
			{
				Console.WriteLine("YES");
				Console.WriteLine(string.Join(' ', sol));
			}
		}

		public static long LowerBound(long min, long max, Predicate<long> test)
		{
			long e = max;
			long s = min;

			while (s < e)
			{
				long mid = (s + e) / 2;
				if (test(mid))
					e = mid;
				else
					s = mid + 1;
			}

			return e;
		}

		public static long UpperBound(long min, long max, Predicate<long> test)
		{
			long s = min;
			long e = max;

			while (s < e)
			{
				long mid = (s + e) / 2;
				if (test(mid))
					s = mid + 1;
				else
					e = mid;
			}

			return s - 1;
		}

		public static (int, int)[] GetPairs(int count)
		{
			var qs = new (int, int)[count];
			for (int i = 0; i < count; i++)
			{
				var line = Console.ReadLine();
				int spacePos = 1;
				while (line[spacePos] != ' ')
					spacePos++;

				var l = int.Parse(line.AsSpan(0, spacePos));
				var r = int.Parse(line.AsSpan(spacePos + 1, line.Length - spacePos - 1));
				qs[i] = (l - 1, r - 1);
			}

			return qs;
		}

		public static int[] GetInts(int count)
		{
			var str = Console.ReadLine();
			var a = new int[count];

			var currentStart = 0;
			for (int i = 0; i < count - 1; i++)
			{
				int currentEnd = currentStart + 1;
				while (str[currentEnd] != ' ')
					currentEnd++;

				a[i] = int.Parse(str.AsSpan(currentStart, currentEnd - currentStart));
				currentStart = currentEnd + 1;
			}

			a[a.Length - 1] = int.Parse(str.AsSpan(currentStart, str.Length - currentStart));
			return a;
		}
	}

}


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

class Program
{
	int[][] c;
	int n, m;
	int mod = 1000000007;
	int add(int x, int y)
	{
		x+=y;
		return x < mod ? x : x - mod;
	}
	int mul(int x, int y)
	{
		return Convert.ToInt32(Convert.ToInt64(x) * y % mod);
	}
	void run()
	{
		String[] str = Console.ReadLine().Split(' ');
		n = Convert.ToInt32(str[0]);
		m = Convert.ToInt32(str[1]);
		int[][] dp=new int[n+1][];
		for (int i = 1; i <= n; i++)
		{
			dp[i] = new int[m-1];
			if (i == 1)
			{
				for (int j = 0; j <= m - 2; j++)
					dp[i][j] = 1;
				continue;
			}
			int now = 0;
			for (int j = 0; j <= m-2; j++)
			{
				now= add(now,dp[i-1][j]);
				dp[i][j] = add(j == 0 ? 0 : dp[i][j - 1], now);
			}
		}

		int[][] sum = new int[n+1][];
		for (int i = 0; i <= n; i++)
		{
			sum[i] = new int[m - 1];
			for (int j = 0; j <= m - 2; j++)
				sum[i][j] = i == 0 ? 0 : sum[i - 1][j] + dp[i][j];
		}

		int res = 0;
		for (int i = 1; i <= n; i++)
			for (int j = 0; j <= m - 2; j++)
			{
				res = add(res, mul(mul(sum[i][j], add(sum[n - i + 1][j], mod - sum[n - i][j])), m - 1 - j));
			}
		Console.WriteLine(res);
	}
	static void Main(String[] args)
	{
		new Program().run();
	}
}


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

class Program
{
	int[][] c;
	int n, m;
	int mod = 1000000007;
	int add(int x, int y)
	{
		x+=y;
		return x < mod ? x : x - mod;
	}
	int mul(int x, int y)
	{
		return Convert.ToInt32(Convert.ToInt64(x) * y % mod);
	}
	void run()
	{
		String[] str = Console.ReadLine().Split(' ');
		n = Convert.ToInt32(str[0]);
		m = Convert.ToInt32(str[1]);
		int[][] dp=new int[n+1][];
		for (int i = 1; i <= n; i++)
		{
			dp[i] = new int[m-1];
			if (i == 1)
			{
				for (int j = 0; j <= m - 2; j++)
					dp[i][j] = 1;
				continue;
			}
			int now = 0;
			for (int j = 0; j <= m-2; j++)
			{
				now= add(now,dp[i-1][j]);
				dp[i][j] = add(j == 0 ? 0 : dp[i][j - 1], now);
			}
		}

		int[][] sum = new int[n+1][];
		for (int i = 0; i <= n; i++)
		{
			sum[i] = new int[m - 1];
			for (int j = 0; j <= m - 2; j++)
				sum[i][j] = i == 0 ? 0 : add(sum[i - 1][j] , dp[i][j]);
		}

		int res = 0;
		for (int i = 1; i <= n; i++)
			for (int j = 0; j <= m - 2; j++)
			{
				res = add(res, mul(mul(sum[i][j], add(sum[n - i + 1][j], mod - sum[n - i][j])), m - 1 - j));
			}
		Console.WriteLine(res);
	}
	static void Main(String[] args)
	{
		new Program().run();
	}
}


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

namespace Codeforces
{
    class E
    {
        private static ThreadStart  s_threadStart = new E().Go;

        class Point
        {
            public int X, Y;
            public bool Keep;
        }

        private void Go()
        {
            long mod = 1000000007;

            int n = GetInt();
            Point[] points = new Point[n];
            for (int i = 0; i < n; i++)
            {
                points[i] = new Point() { X = GetInt(), Y = GetInt() };
            }

            Dictionary<int, List<int>> xDict = new Dictionary<int, List<int>>();
            Dictionary<int, List<int>> yDict = new Dictionary<int, List<int>>();
            for(int i = 0; i < n; i++)
            {
                List<int> list;
                if (!xDict.TryGetValue(points[i].X, out list))
                    list = xDict[points[i].X] = new List<int>();

                list.Add(i);

                if (!yDict.TryGetValue(points[i].Y, out list))
                    list = yDict[points[i].Y] = new List<int>();

                list.Add(i);
            }

            long ans = 1;

            int k = n;
            for (int i = 0; i < n; i++)
            {
                if (xDict[points[i].X].Count == 1 && yDict[points[i].Y].Count == 1)
                {
                    ans *= 3;
                    ans %= mod;
                    xDict.Remove(points[i].X);
                    yDict.Remove(points[i].Y);
                    k--;
                }
            }

            int m = xDict.Count() + yDict.Count();

            ans *= Bin(m, k, mod);
            ans %= mod;
            Wl(ans);
        }

        long Bin(long n, long k, long mod)
        {
            if (n < 2) return 1;

            long[] bin = new long[k + 1]; bin[0] = 1; bin[1] = 1;
            long[] next = new long[k + 1];
            long[] t;

            for (int i = 2; i <= k; i++)
            {
                next[0] = 1; next[i] = 1;
                for (int j = 1; j <= k && j < i; j++)
                    next[j] = (bin[j] + bin[j - 1]) % mod;

                t = bin;
                bin = next;
                next = t;
            }

            long ans = 0;
            for (int i = 0; i <= k; i++)
            {
                ans += bin[i];
                ans %= mod;
            }
            return ans;
        }

        #region Template

        private static StringBuilder output = new StringBuilder();

        public static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            output.Length = 0;
            Thread main = new Thread(new ThreadStart(s_threadStart), 512 * 1024 * 1024);
            timer.Start();
            main.Start();
            main.Join();
            Console.Write(output);
            timer.Stop();
            Console.Error.WriteLine(timer.ElapsedMilliseconds);
        }

        private static IEnumerator<string> ioEnum;
        private static string GetString()
        {
            do
            {
                while (ioEnum == null || !ioEnum.MoveNext())
                {
                    ioEnum = Console.ReadLine().Split().AsEnumerable().GetEnumerator();
                }
            } while (string.IsNullOrEmpty(ioEnum.Current));

            return ioEnum.Current;
        }

        private static int GetInt()
        {
            return int.Parse(GetString());
        }

        private static long GetLong()
        {
            return long.Parse(GetString());
        }

        private static double GetDouble()
        {
            return double.Parse(GetString());
        }

        private static List<int> GetIntArr(int n)
        {
            List<int> ret = new List<int>(n);
            for (int i = 0; i < n; i++)
            {
                ret.Add(GetInt());
            }
            return ret;
        }

        private static void Wl<T>(T o)
        {
            W(o);
            output.Append(Console.Out.NewLine);
        }

        private static void Wl<T>(IEnumerable<T> enumerable)
        {
            W(enumerable);
            output.Append(Console.Out.NewLine);
        }

        private static void W<T>(T o)
        {
            if (o is double)
            {
                Wd((o as double?).Value, "");
            }
            else if (o is float)
            {
                Wd((o as float?).Value, "");
            }
            else
                output.Append(o.ToString());
        }

        private static void W<T>(IEnumerable<T> enumerable)
        {
            W(string.Join(" ", enumerable.Select(e => e.ToString()).ToArray()));
        }

        private static void Wd(double d, string format)
        {
            W(d.ToString(format, CultureInfo.InvariantCulture));
        }

        #endregion
    }
}