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 Go (1.6) (judge verdict: Accepted)

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	sc := NewScanner()

	k := sc.ReadInt()
	if k < 10 {
		fmt.Println(k)
		return
	}

	dpTable := make([][]int, 1)
	// dynamic planning table[row index][column index]
	//
	// row index: the length of lunlun numbers - 1
	//   e.g. dpTable[2] means the length is 3. 123, 234, etc.
	//
	// column index:
	//   * 0 is dummy
	//   * 1 to 10 is the [row index - 1]th number + 1
	//     e.g. dpTable[2][5] means the 3rd number is 4. 432, 443, etc.
	//          dpTable[2][1] means the 3rd number is 0. 001, 012, etc.
	//   * 11 is dummy
	//
	// cell: the count of lunlun numbers
	//   e.g. dpTable[2][5] == 100 (really it is wrong) means
	//        the count of lunlun numbers like "4**" is 100.
	//        dbTable[*][0 or 11] is always 0.

	// fill zeroth row
	// Let 0 be a lunlun number though in fact it is not.
	dpRow0 := make([]int, 12)
	dpTable[0] = dpRow0
	for i := 1; i <= 10; i++ {
		dpRow0[i] = 1
	}

	// fill first row and more
	lunlunCount := 9 // do not include 0 here
	rowI := 0        // row index
	colI := 1        // column index
	for lunlunCount < k {
		rowI++
		dpPrevRow := dpTable[rowI-1]
		dpRow := make([]int, 12)
		dpTable = append(dpTable, dpRow)
		for colI = 1; colI <= 10; colI++ {
			dpRowI := dpPrevRow[colI-1] + dpPrevRow[colI] + dpPrevRow[colI+1]
			dpRow[colI] = dpRowI

			// If colI == 1, the number has leading zero,
			// so lunlunCount does not include it.
			if colI > 1 {
				lunlunCount += dpRowI
				if lunlunCount >= k {
					break
				}
			}
		}
	}

	restLunlunCount := k - (lunlunCount - dpTable[rowI][colI])
	// The [k]th lunlun number belongs to dpTable[rowI][colI] and
	// it is [restLunlunCount]th number there.

	// compute the answer with determining where the [k]th lunlun number
	// belongs to in every row
	answer := int64(colI - 1)
	for rowI > 0 {
		rowI--
		colI--
		checkedLunlunCount := 0
		for i := 0; i < 3; i++ {
			next := dpTable[rowI][colI]
			if checkedLunlunCount+next >= restLunlunCount {
				answer = answer*10 + int64(colI-1)
				restLunlunCount -= checkedLunlunCount
				break
			}
			checkedLunlunCount += next
			colI++
		}
	}

	fmt.Println(answer)
}

// util
// *   math(int)

func AbsInt(x int) int {
	if x >= 0 {
		return x
	}
	return -x
}

func MinInt(values ...int) int {
	if len(values) == 0 {
		panic("no values")
	}
	min := values[0]
	for _, v := range values {
		if v < min {
			min = v
		}
	}
	return min
}

func MaxInt(values ...int) int {
	if len(values) == 0 {
		panic("no values")
	}
	max := values[0]
	for _, v := range values {
		if v > max {
			max = v
		}
	}
	return max
}

func PowInt(base int, exponent uint) int {
	answer := 1
	for i := uint(0); i < exponent; i++ {
		answer *= base
	}
	return answer
}

// *   math(int)

func AbsInt64(x int64) int64 {
	if x >= 0 {
		return x
	}
	return -x
}

func MinInt64(values ...int64) int64 {
	if len(values) == 0 {
		panic("no values")
	}
	min := values[0]
	for _, v := range values {
		if v < min {
			min = v
		}
	}
	return min
}

func MaxInt64(values ...int64) int64 {
	if len(values) == 0 {
		panic("no values")
	}
	max := values[0]
	for _, v := range values {
		if v > max {
			max = v
		}
	}
	return max
}

func PowInt64(base int64, exponent uint) int64 {
	answer := int64(1)
	for i := uint(0); i < exponent; i++ {
		answer *= base
	}
	return answer
}

// * io

type Scanner struct {
	bufScanner *bufio.Scanner
}

func NewScanner() *Scanner {
	bufSc := bufio.NewScanner(os.Stdin)
	bufSc.Split(bufio.ScanWords)
	return &Scanner{bufSc}
}

func (sc *Scanner) ReadString() string {
	bufSc := sc.bufScanner
	bufSc.Scan()
	return bufSc.Text()
}

func (sc *Scanner) ReadInt() int {
	bufSc := sc.bufScanner
	bufSc.Scan()
	text := bufSc.Text()

	num, err := strconv.Atoi(text)
	if err != nil {
		panic(err)
	}
	return num
}