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.Collections;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System;
using System.Numerics;

class Program
{
    static void Main()
    {
        int K = ReadInt;
        List<long> ans = new List<long>();

        for (int i = 1; i <= 9; i++)
        {
            ans.Add(i);
            DFS(ans, i);
        }

        ans.Sort();

        WriteLine(ans[K-1]);
        ReadLine();
    }

    static void DFS(List<long> ans,long n)
    {
        if (Log10(n) + 1 > 10) return;
        char[] cs = n.ToString().ToCharArray();
        for (int i = Max(0,cs[cs.Length-1]-'1'); i <= Min(cs[cs.Length - 1] -'0'+1, 9); i++)
        {
            long newN = long.Parse(string.Join("", cs)) * 10 + i;
            ans.Add(newN);
            DFS(ans, newN);
        }
    }


    public static long GetInv(long a, long mod)
    {
        return PowerMod(a, mod - 2, mod);
    }
    public static long Combination(long a, long b, long mod)
    {
        if (b < 0 || b > a) return 0;
        if (b > a / 2) b = a - b;
        long numerator = Factorial(a, mod);
        long denominator = (Factorial(b, mod) * Factorial(a - b, mod)) % mod;

        return (numerator * GetInv(denominator, mod)) % mod;
    }
    public static long Factorial(long n, long mod)
    {
        if (n == 0) return 1;
        if (n == 1) return 1;
        long ans = n;
        for (int i = 2; i < n; i++)
        {
            ans = (ans * i) % mod;
        }

        return ans;
    }
    private static long PowerMod(long a, long n, long mod)
    {
        if (n == 1) return a;

        long p = PowerMod(a, n / 2, mod);
        if (n % 2 == 1) return ((p * p) % mod * a) % mod;
        else return (p * p) % mod;
    }


    struct Vector2Int
    {
        public Vector2Int(int x, int y)
        {
            X = x;
            Y = y;
        }
        public int X;
        public int Y;
        public double Magnitude => Math.Sqrt(X * X + Y * Y);

        public static Vector2Int zero => new Vector2Int(0, 0);
        public static Vector2Int u => new Vector2Int(0, 1);
        public static Vector2Int r => new Vector2Int(1, 0);
        public static Vector2Int d => new Vector2Int(0, -1);
        public static Vector2Int l => new Vector2Int(-1, 0);
        public static Vector2Int[] AllDirections => new Vector2Int[4] { u, r, d, l };
        public static Vector2Int[] AllDirections8 => new Vector2Int[8] { u, r, d, l, u + r, r + d, d + l, l + u };


        public static Vector2Int operator +(Vector2Int a, Vector2Int b)
        {
            return new Vector2Int(a.X + b.X, a.Y + b.Y);
        }
        public static Vector2Int operator -(Vector2Int a, Vector2Int b)
        {
            return new Vector2Int(a.X - b.X, a.Y - b.Y);
        }
        public static bool operator ==(Vector2Int a, Vector2Int b)
        {
            return a.X == b.X && a.Y == b.Y;
        }
        public static bool operator !=(Vector2Int a, Vector2Int b)
        {
            return a.X != b.X || a.Y != b.Y;
        }
        public static Vector2Int operator *(Vector2Int v, int n)
        {
            return new Vector2Int(v.X * n, v.Y * n);
        }
        public static Vector2Int operator *(int n, Vector2Int v)
        {
            return new Vector2Int(v.X * n, v.Y * n);
        }
    }
    struct Vector3Int
    {
        public Vector3Int(int x, int y, int z)
        {
            X = x;
            Y = y;
            Z = z;
        }
        public int X;
        public int Y;
        public int Z;

        public double Magnitude => Math.Sqrt(X * X + Y * Y + Z * Z);

        public static Vector3Int zero => new Vector3Int(0, 0, 0);
        public static Vector3Int u => new Vector3Int(0, 1, 0);
        public static Vector3Int r => new Vector3Int(1, 0, 0);
        public static Vector3Int d => new Vector3Int(0, -1, 0);
        public static Vector3Int l => new Vector3Int(-1, 0, 0);

        public static Vector3Int operator +(Vector3Int a, Vector3Int b)
        {
            return new Vector3Int(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
        }
        public static Vector3Int operator -(Vector3Int a, Vector3Int b)
        {
            return new Vector3Int(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
        }
        public static bool operator ==(Vector3Int a, Vector3Int b)
        {
            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
        }
        public static bool operator !=(Vector3Int a, Vector3Int b)
        {
            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;
        }
        public static Vector3Int operator *(Vector3Int v, int n)
        {
            return new Vector3Int(v.X * n, v.Y * n, v.Z * n);
        }
        public static Vector3Int operator *(int n, Vector3Int v)
        {
            return new Vector3Int(v.X * n, v.Y * n, v.Z * n);
        }
    }

    #region Reader
    static Vector2Int ReadVec2Int
    {
        get
        {
            string[] s = Console.ReadLine().Split(' ');
            return new Vector2Int(int.Parse(s[0]), int.Parse(s[1]));
        }
    }
    static Vector2Int[] ReadVec2Ints(int n)
    {
        List<Vector2Int> list = new List<Vector2Int>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadInts;
            list.Add(new Vector2Int(ab[0], ab[1]));
        }
        return list.ToArray();
    }
    static HashSet<Vector2Int> ReadVec2IntHash(int n)
    {
        HashSet<Vector2Int> hash = new HashSet<Vector2Int>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadInts;
            hash.Add(new Vector2Int(ab[0], ab[1]));
        }
        return hash;
    }
    static string ReadStr => Console.ReadLine();
    static string[] ReadStrs => Console.ReadLine().Split(' ');
    static int ReadInt => Convert.ToInt32(Console.ReadLine());
    static int[] ReadInts => Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
    static long ReadLong => Convert.ToInt64(Console.ReadLine());
    static long[] ReadLongs => Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray();
    static long[,] ReLongMatrix(int r, int c)
    {
        var mat = new long[r, c];
        for (int i = 0; i < r; ++i)
        {
            var x = ReadLongs;
            for (int j = 0; j < c; ++j)
            {
                mat[i, j] = x[j];
            }
        }
        return mat;
    }
    static Tuple<string, string>[] ReTupleStr(int n)
    {
        List<Tuple<string, string>> list = new List<Tuple<string, string>>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadStrs;
            list.Add(new Tuple<string, string>(ab[0], ab[1]));
        }
        return list.ToArray();
    }
    static Tuple<long, long>[] ReTupleLong(int n)
    {
        List<Tuple<long, long>> list = new List<Tuple<long, long>>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadLongs;
            list.Add(new Tuple<long, long>(ab[0], ab[1]));
        }
        return list.ToArray();
    }
    static Tuple<int, int>[] ReadTupleInt(int n)
    {
        List<Tuple<int, int>> list = new List<Tuple<int, int>>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadInts;
            list.Add(new Tuple<int, int>(ab[0], ab[1]));
        }
        return list.ToArray();
    }
    static Tuple<double, double>[] ReTupleDouble(int n)
    {
        List<Tuple<double, double>> list = new List<Tuple<double, double>>();
        for (int i = 0; i < n; ++i)
        {
            var ab = ReadLongs;
            list.Add(new Tuple<double, double>(ab[0], ab[1]));
        }
        return list.ToArray();
    }
    static Dictionary<int, HashSet<int>> ReAdjacencyList(int N, int M)
    {
        Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();
        for (int i = 0; i <= N; ++i)
        {
            dict.Add(i, new HashSet<int>());
        }
        for (int i = 0; i < M; ++i)
        {
            var ab = ReadInts;
            dict[ab[0]].Add(ab[1]);
            dict[ab[1]].Add(ab[0]);
        }
        return dict;
    }
    #endregion
    static void Swap<T>(ref T a,ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }

    static long mod = (int)Pow(10, 9) + 7;

}