Problem:
Score : 400 points

Problem Statement

A positive integer X is said to be a lunlun number if and only if the following condition is satisfied:

In the base ten representation of X (without leading zeros), for every pair of two adjacent digits, the absolute difference of those digits is at most 1.

For example, 1234, 1, and 334 are lunlun numbers, while none of 31415, 119, or 13579 is.

You are given a positive integer K. Find the K-th smallest lunlun number.

Constraints

1 \leq K \leq 10^5

All values in input are integers.

Input

Input is given from Standard Input in the following format:

K

Output

Print the answer.

Sample Input 1

15

Sample Output 1

23

We will list the 15 smallest lunlun numbers in ascending order:

1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
21,
22,
23.

Thus, the answer is 23.

Sample Input 2

1

Sample Output 2

1

Sample Input 3

13

Sample Output 3

21

Sample Input 4

100000

Sample Output 4

3234566667

Note that the answer may not fit into the 32-bit signed integer type.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using static System.Math;
using static System.Array;
using static AtCoder.Tool;
namespace AtCoder
{
    class AC
    {
        //const int MOD = 1000000007;
        const int MOD = 998244353;
        const int INF = int.MaxValue / 2;
        const long SINF = long.MaxValue / 2;
        const double EPS = 1e-8;
        static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 };
        static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 };
        //static List<List<int>> G = new List<List<int>>();
        //static List<List<Edge>> G = new List<List<Edge>>();
        //static List<Edge> E = new List<Edge>();
        static void Main(string[] args)
        {
            //var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            //Console.SetOut(sw);
            var cin = new IO_ShortCut();

            int K = cin.Int;
            if (K < 10) { cin.OutL(K); return; }
            var ans = new List<long>();
            for (var i = 1; i <= 9; i++) ans.Add(i);

            int cn = 9;
            int ls = 8;

            while (ans.Count() < K)
            {
                int ad = 0;
                for(var i = 0; i < cn; i++)
                {
                    long nx = ans[ls - i] % 10;
                    ans.Add(ans[ls - i] * 10 + nx);ad++;
                    if (nx > 0) { ans.Add(ans[ls - i] * 10 + nx - 1);ad++; }
                    if (nx < 9) { ans.Add(ans[ls - i] * 10 + nx + 1);ad++; }
                }
                cn = ad;
                ls = ans.Count() - 1;
            }
            ans.Sort();
            //cin.Out_Sep(ans);
            cin.OutL(ans[K - 1]);
            


            //Console.Out.Flush();
        }
        
        struct Edge
        {
            public int from;

            public int to;
            public long dist;
            public Edge(int t, long c)
            {
                from = -1;
                to = t;
                dist = c;
            }
            public Edge(int f, int t, long c)
            {
                from = f;
                to = t;
                dist = c;
            }
        }
        
    }
    
    class IO_ShortCut
    {
        public IO_ShortCut() { }
        public string[] ReadSplit => Console.ReadLine().Split();
        public int[] ReadSplitInt => ConvertAll(Console.ReadLine().Split(), int.Parse);
        public long[] ReadSplitLong => ConvertAll(Console.ReadLine().Split(), long.Parse);
        public double[] ReadSplit_Double => ConvertAll(Console.ReadLine().Split(), double.Parse);
        public string Str => Console.ReadLine();
        public int Int => int.Parse(Console.ReadLine());
        public long Long => long.Parse(Console.ReadLine());
        public double Double => double.Parse(Console.ReadLine());
        public T Conv<T>(string input) => (T)Convert.ChangeType(input, typeof(T));
        public void Input<T>(out T a) => a = Conv<T>(Console.ReadLine());
        public void Input<T, U>(out T a, out U b)
        { var q = ReadSplit;a = Conv<T>(q[0]);b = Conv<U>(q[1]); }
        public void Input<T, U, V>(out T a, out U b, out V c)
        { var q = ReadSplit;a = Conv<T>(q[0]);b = Conv<U>(q[1]);c = Conv<V>(q[2]); }
        public void Input<T, U, V, W>(out T a, out U b, out V c, out W d)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]);d = Conv<W>(q[3]); }

        public void OutL(object s) => Console.WriteLine(s);
        public void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s));
        public void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s));
        public void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s));
        public void Out_One(object s) => Console.Write($"{s} ");
        public void Out_One(object s, string sep) => Console.Write($"{s}{sep}");
    }
    public static class Tool
    {
        static public void Initialize<T>(ref T[] array, T initialvalue)
        {
            array = ConvertAll(array, x => initialvalue);
        }
        static public void Swap<T>(ref T a, ref T b)
        {
            T keep = a;
            a = b;
            b = keep;
        }
        static public void Display<T>(T[,] array2d, int n, int m)
        {
            for (var i = 0; i < n; i++)
            {
                for (var j = 0; j < m; j++)
                {
                    Console.Write($"{array2d[i, j]} ");
                }
                Console.WriteLine();
            }
        }
        static public long LPow(int a, int b) => (long)Pow(a, b);
    }
    class Modulo
    {
        private int M;
        private readonly long[] m_facs;
        public long Mul(long a, long b)
        {
            return ((a * b) % M);
        }
        public Modulo(long n, int m)
        {
            M = m;
            m_facs = new long[n + 1];
            m_facs[0] = 1;
            for (long i = 1; i <= n; ++i)
            {
                m_facs[i] = Mul(m_facs[i - 1], i);
            }
        }
        public long Fac(long n)
        {
            return m_facs[n];
        }
        public long Pow(long a, long m)
        {
            switch (m)
            {
                case 0:
                    return 1L;
                case 1:
                    return a;
                default:
                    long p1 = Pow(a, m / 2);
                    long p2 = Mul(p1, p1);
                    return ((m % 2) == 0) ? p2 : Mul(p2, a);
            }
        }
        public long Div(long a, long b)
        {
            return Mul(a, Pow(b, M - 2));
        }
        public long Ncr(long n, long r)
        {
            if (n < r) { return 0; }
            if (n == r) { return 1; }
            long res = Fac(n);
            res = Div(res, Fac(r));
            res = Div(res, Fac(n - r));
            return res;
        }
    }
}