import java.io.*;
import java.math.*;
import java.util.*;

public class Main {
	//static final long MOD = 998244353;
	static final long MOD = 1000000007;
	static final int INF = 1000000007;
	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		int N = sc.ni();
		for (int a = 1; a < 10; a++) {
			for (int b = 1; b < 10; b++) {
				if (a*b==N) {
					System.out.println("Yes");
					return;
				}
			}
		}
		System.out.println("No");
	}

    public static long power(long x, long y, long p) {
        // Initialize result
        long res = 1;

        // Update x if it is more
        // than or equal to p
        x = x % p;

        while (y > 0)
        {
            // If y is odd, multiply x
            // with result
            if((y & 1)==1)
                res = (res * x) % p;

            // y must be even now
            // y = y / 2
            y = y >> 1;
            x = (x * x) % p;
        }
        return res;
    }

    public static long dist(int[] point, int[] point2) {
    	return (long)(Math.pow((point2[1]-point[1]),2)+Math.pow((point2[0]-point[0]),2));
    }

    public static long gcd(long a, long b) {
    	if (b == 0)
    		return a;
    	else
    		return gcd(b,a%b);
    }

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr2[1]-arr1[1];
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.io.*;
import java.util.*;
class Main{
    public static void main(String[] args) throws Exception {
		hayami saori = new hayami();
		int N = saori.saori_hayami();
		int ans = 0;
		boolean flg = false;

		for(int i = 1;i <=9;i++){
			if(N % i == 0){
				ans = N/i;
				if(ans < 10){
					flg = true;
				}
			}
		}
		if(flg){
			System.out.println("Yes");
		} else{
			System.out.println("No");
		}

    }
}

class hayami implements Closeable {
	private final InputStream in = System.in;
	private final byte[] hayami = new byte[1024];
	private int Hayami = 0;
	private int saori = 0;
	private boolean HayamiSaori() {
		if (Hayami < saori) {
			return true;
		}else{
			Hayami = 0;
			try {
				saori = in.read(hayami);
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (saori <= 0) {
				return false;
			}
		}
		return true;
	}
	private int SaoriHayami() {
		if (HayamiSaori()) {
            return hayami[Hayami++];
         }else{
             return -1;
         }
	}
	private static boolean hayami_saori(int hayami) {
		return 33 <= hayami && hayami <= 126;
	}
	public boolean hayamisaori() {
		while(HayamiSaori() && !hayami_saori(hayami[Hayami])) Hayami++; return HayamiSaori();
	}
	public String nextHayami() {
		if (!hayamisaori()) throw new NoSuchElementException();
		StringBuilder hayamin = new StringBuilder();
		int saori = SaoriHayami();
		while(hayami_saori(saori)) {
			hayamin.appendCodePoint(saori);
			saori = SaoriHayami();
		}
		return hayamin.toString();
	}
	public long saorihayami() {//nextLong
		if (!hayamisaori()) throw new NoSuchElementException();
		long hayami = 0;
		boolean misao = false;
		int saori = SaoriHayami();
		if (saori == '-') {
			misao = true;
			saori = SaoriHayami();
		}
		if (saori < '0' || '9' < saori) {
			throw new NumberFormatException();
		}
		while(true){
			if ('0' <= saori && saori <= '9') {
				hayami *= 10;
				hayami += saori - '0';
			}else if(saori == -1 || !hayami_saori(saori)){
				return misao ? -hayami : hayami;
			}else{
				throw new NumberFormatException();
			}
			saori = SaoriHayami();
		}
	}
	public int saori_hayami() {//nextInt
		long hayami = saorihayami();
		if (hayami < Integer.MIN_VALUE || hayami > Integer.MAX_VALUE) throw new NumberFormatException();
		return (int) hayami;
	}
	public double Hayamin() { //nextDouble
		return Double.parseDouble(nextHayami());
	}
	public void close() {
		try {
			in.close();
		} catch (IOException e) {
		}
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws Exception {

		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(reader.readLine());
		boolean flag = false;
		outer:
		for (int A = 1; A <= 9; A++) {
			for (int B = 1; B <= 9; B++) {
				if (N == A * B) {
					System.out.println("Yes");
					flag = true;
					break outer;
				}
			}
		}
		if (!flag) {
			System.out.println("No");
		}
	}
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		boolean check = false;
		int c = 1;
		for(int i = 1; i<10; i++){

			if(check == false){

				for(int j =c; j <10; j++){

					if(i*j == n){
						check = true;
						break;
					}

				}

			}else{
				break;
			}
		}

		if(check){
			System.out.println("YES");
		}else{
			System.out.println("NO");

		}

	}
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		boolean check = false;
		for(int i = 1; i<10; i++){
			if(check == false){
				for(int j =1; j <10; j++){
					if(i*j == n){
						check = true;
						break;
					}
				}
			}else{
				break;
			}
		}

		if(check){
			System.out.println("YES");
		}else{
			System.out.println("NO");

		}

	}
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		boolean check = false;
		for(int i = 1; i<10; i++){
			if(check == false){
				for(int j =1; j <10; j++)
				if(i*j == n){
					check = true;
					break;
				}
			}else{
				break;
			}
		}
		if(check){
			System.out.println("YES");
		}else{
			System.out.println("NO");

		}

	}
}


#include<stdio.h>

int main()
{
int m,flag=0;
    scanf("%d",&m);

    for(int i=1;i<=9;i++)
    {for(int j=1;j<=9;j++){
            if(i*j==m)
            {flag=1;break;}

        }}
    if(flag==1) printf("Yes");
    else printf("No");
return 0;
}


#include <stdio.h>

int main()
{
    int N;
    scanf("%d", &N);
    for(int i=1; i<10; i++){
        for(int j=1; j<10; j++){
            if(i*j == N){
                printf("Yes\n");
                return 0;
            }
        }
    }
    printf("No\n");
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using ll = long long;
constexpr int INF = numeric_limits<int>::max();
template <typename T, typename... Args>
const T& min(const T& a, Args... args) {
  return min(a, min(args...));
}
template <typename T, typename... Args>
const T& max(const T& a, Args... args) {
  return max(a, max(args...));
}

#pragma GCC optimize("O3")
static const auto __ = [] {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  return nullptr;
}();

int main(int argc, char* argv[]) {
  int n;
  cin >> n;
  for (int a = 1; a < 10; ++a) {
    for (int b = 1; b< 10; ++b) {
      if (a * b == n) {
        cout << "Yes" << '\n';
        return 0;
      }
    }
  }
  cout << "No" << '\n';
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

int main(){
  string S;
  cin >> S;
  int A[20];
  int ans = 0;
  int myans =0;
  for (int i=0;i<S.size();i++){
    if(S[i] == 'A' || S[i]=='C' || S[i] =='G' || S[i] =='T'){
      A[i]=1;
    }else{
      A[i]=0;
    }
  }
  for(int i=0;i<=S.size();i++){
    if(A[i]!=0){
      ans++;
    }else{
      myans = max(myans,ans);
      ans=0;
    }
//    cout << S.substr(i,3) << endl;
  }
  cout << myans << endl;

  return 0;
}


#include <bits/stdc++.h>
using namespace std;

int main(){
  int N;
  cin >> N;
  bool flag = false;
  for(int i=1;<10;i++){
    for (int j=1;<10<j++){
      if (i*j == N) flag = true;
    }
  }
  if (flag){
    cout << "Yes";
  }else{
    cout << "No";
  }
  cout << endl;

  return 0;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main(){
  int n;
  cin>>n;
  bool answer=false;
  for(int i=1;i<=9;i++){
    for(int j=1;j<=9;j++){
    	if(n==i*j) anwer=true;
    }
  }
  if(answer) printf("Yes");
  else printf("No");
}


#include<stdio.h>
int main()
{
    int n,i,j,flag=0;
    scanf("%d",&n);
    for(i=1;i<=9;i++)
    {
        for(j=1;j<=9;j++)
        {
            if(i*j==n)
                flag=1;
        }

    }
    if(flag==1)
    printf("Yes\n");
    else
        printf("No\n");

}


#include <unistd.h>

int main()
{
    char buf[4] = {0};  // 入力バッファ（0で初期化）
    int N = 0;      // 入力された数値

    int len = 0;        // 入力された文字列の長さ
    int rank = 1;       // 位

    // 標準入力から4バイト読み込みバッファに格納
    read(0, buf, 4);

    // 入力された文字列の長さをはかる
    for (int i = 1; i < 4; i++) {
        if (buf[i] != 0) {
            len++;
        }
    }

    // Nに入力された数値を格納
    for (int i = len; i > 0; i--) {
        N += (int)((buf[i-1] - 0x30) * rank);   // 文字'0'はASCIIで0x30のため
        rank = rank * 10;
    }

    // 本題
    for (int i = 1; i < 10; i++) {
        for (int j = 1; j < 10; j++) {
            if (N == (i * j)) {
                write(1, "Yes\n", 4);
                return 0;
            }
        }
    }

    write(1, "No\n", 3);

    return 0;
}


#include <stdio.h>

int main(void)
{
    int n;

    scanf("%d", &n);

    for (int a=1; a<=9; a++) {
        for (int b=1; b<=9; b++) {
            if (a*b==n) {
                printf("Yes");
                return 0;
            }
        }
    }

    printf("No");

    return 0;
}


#include <stdio.h>
int main()
{
    int n;
    scanf("%d",&n);

    if(n==1*1 || n==2*2 || n==3*3 || n==4*4 ||n==5*5 ||n==6*6|| n==7*7||n==8*8||n==9*9)
    {
        printf("Yes");

    }
    else if (n==10||n==20||n==30||n==40)
        {
            printf("Yes");
        }
    else
    {
        printf("No\n");
    }
     return 0;
}


#include<stdio.h>
int main()
{
    int n,i,d,j,l;

    scanf("%d",&n);

    for(i=1;i<=9;i++)
    {
        for(j=1;j<=9;j++)
        {
            if(i*j==n) n=l;

            if(i*j==n) break;

            else continue;

        }
    }

     if(n==l) printf("Yes\n");

     else printf("No\n");

return 0;
}


#include <stdio.h>
int main(){
  int i,a;
  scanf("%d",&a);
  for(i=1;i<=9;i++){
    if(a%i==0){
      puts("Yes");
      return 0;
    }
  }
  puts("No");
  return 0;
}


function main(n) {
    for (var i = 1; i <= 9; i++) {
        if (n % i === 0 && n / i < 10) {
            console.log('Yes');
            return;
        }
    }
    console.log('No');
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function main(n) {
    for (var i = 1; i <= 9; i++) {
        if (n % i === 0 && n / i < 10) {
            console.log('Yes');
            process.exit(0);
        }
    }
    console.log('No');
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function main(input){
  input = Number(input);

  for(var i = 1;i < 10;i++){
    if(input % i === 0){
      if(input / i < 10){
        console.log("Yes");
        return;
      }
    }
  }
  console.log("No");
}

main(require("fs").readFileSync("/dev/stdin","utf8"));


function main(lines) {
 const input = lines.split('\n').map(Number)

 let flag = false;
 for(let i=1; i<10; i++){
     if(input[0]%i === 0 && 1<= input[0]/i && input[0]/i <= 9 ){
         flag = true;
         break;
     }
 }

 flag ? console.log('Yes') : console.log('No')
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'));


const input = require("fs").readFileSync("/dev/stdin", "utf8").split("\n");

const N = input[0]

let result = 'No'
for (let i = 1; i <= 9; i++) {
    for (let j = 1; j <= 9; j++) {
        if (i * j == N) {
            result = 'Yes'
        }
    }
}

console.log(result)


process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = []
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

reader.on('line', (line) => {
  lines.push(line);
});

reader.on('close', () => {
 var n = Number(lines[0]);
 for(i=1; i<=9; i++){
   for(j=1 j<=9; j++){
     if(i * j == n){
       console.log(Yes);
     }
   }
 }

 console.log("No");
});


package main

import (
	"fmt"
)

func main() {
	var n int
	fmt.Scan(&n)
	m := make(map[int]bool)
	for i := 1; i <= 9; i++ {
		for j := 1; j <= 9; j++ {
			m[i*j] = true
		}
	}

	if m[n] {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}


package main

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

var mod = 1000000007

func main() {
	r := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscan(r, &n)

	ans := "No"
LOOP:
	for i := 1; i <= 9; i++ {
		for j := 1; j <= 9; j++ {
			if i*j == n {
				ans = "Yes"
				break LOOP
			}
		}
	}

	fmt.Println(ans)
}


package main

import "fmt"

func main() {
	var n int
	fmt.Scan(&n)

	for i := 1; i <= 9; i++ {
		for j := 1; j <= 9; j++ {
			if n == i*j {
				fmt.Println("Yes")
				return
			}
		}
	}

	fmt.Println("No")
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
	"unsafe"
)

func main() {
	N := sc.nextInt()
	if N > 81 {
		no()
		return
	}
	for i := 2; i <= 9; i++ {
		if N%i == 0 {
			if N/i >= 1 && N/i <= 9 {
				yes()
				return
			}
		}
	}
	no()
}

var (
	sc scanner
)

func init() {
	sc = scanner{
		buf: make([]string, 0, 0),
		cur: 0,
		r:   bufio.NewReader(os.Stdin),
	}
}

type scanner struct {
	buf []string
	cur int
	r   *bufio.Reader
}

func (s *scanner) readln() {
	rbuf := make([]byte, 0, 0)
	for {
		line, prefix, err := s.r.ReadLine()
		if err != nil {
			panic(err)
		}
		rbuf = append(rbuf, line...)
		if prefix == false {
			break
		}
	}
	s.cur = 0
	s.buf = strings.Split(*(*string)(unsafe.Pointer(&rbuf)), " ")
}
func (s *scanner) isFull() bool {
	if s.cur == len(s.buf) {
		return true
	}
	return false
}
func (s *scanner) resetCur() {
	s.cur = 0
}
func (s *scanner) next() string {
	if s.cur == 0 {
		s.readln()
	}
	res := s.buf[s.cur]
	s.cur++
	if s.isFull() {
		s.resetCur()
	}
	return res
}
func (s *scanner) nexts() []string {
	s.readln()
	s.resetCur()
	return s.buf
}
func (s *scanner) nextInt() int {
	if s.cur == 0 {
		s.readln()
	}
	res, _ := strconv.Atoi(s.buf[s.cur])
	s.cur++
	if s.isFull() {
		s.resetCur()
	}
	return res
}
func (s *scanner) nextInts() []int {
	s.readln()
	res := make([]int, len(s.buf))
	for i := range s.buf {
		res[i], _ = strconv.Atoi(s.buf[i])
	}
	s.resetCur()
	return res
}
func (s *scanner) nextFloat() float64 {
	if s.cur == 0 {
		s.readln()
	}
	res, _ := strconv.ParseFloat(s.buf[s.cur],
		64)
	s.cur++
	if s.isFull() {
		s.resetCur()
	}
	return res
}
func (s *scanner) nextFloats() []float64 {
	s.readln()
	res := make([]float64, len(s.buf))
	for i := range s.buf {
		res[i], _ = strconv.ParseFloat(s.buf[i],
			64)
	}
	s.resetCur()
	return res
}
func digits(x int) int {
	return len(strconv.Itoa(x))
}
func powInt(x, p int) (result int) {
	result = 1
	for i := 0; i < p; i++ {
		result *= x
	}
	return
}
func max(x, y int) int {
	return int(math.Max(float64(x), float64(y)))
}
func min(x, y int) int {
	return int(math.Min(float64(x), float64(y)))
}
func abs(x int) int {
	return int(math.Abs(float64(x)))
}
func varDump(value ...interface{}) {
	for _, v := range value {
		fmt.Fprintf(os.Stderr, "%#v\n", v)
	}
}
func yes() {
	fmt.Println("Yes")
}
func no() {
	fmt.Println("No")
}

// Pair a
type Pair struct {
	first  int
	second int
}

// Queue a
type Queue struct {
	v []Pair
}

// Push for queue
func (q *Queue) Push(v Pair) {
	q.v = append(q.v, v)
}

// Pop for queue
func (q *Queue) Pop() Pair {
	r := q.v[0]
	q.v = q.v[1:]
	return r
}

// Front for queue
func (q Queue) Front() Pair {
	return q.v[0]
}

// Empty return true if empty
func (q Queue) Empty() bool {
	return len(q.v) == 0
}


package main

func main() {
	var n int
	fmt.Scan(&n)
	for i := 1; i <= 9; i++ {
		for j := 1; j <= 9; j++ {
			if n == i*j {
				fmt.Println("Yes")
				os.Exit(0)
			}
		}
	}
	fmt.Println("No")
}


package main

import (
  "fmt"
)

func main() {
  var output := "No"
  var n int
  n = fmt.Scan(&n)

  var slice [81]int
  for i := 0; i < 10; i++ {
    for j := 0; j < 10; j++ {
      if n == i*j {
        output := "Yes"
      }
    }
  }

  fmt.Println(output)
}


n = gets.chomp.to_i
result = "No"
10.times do  |i|
  next if i == 0
  result = "Yes"  if n % i == 0 && n/i <10
end

puts result


n = gets.chomp.to_i

1.upto(9) do |i|
  1.upto(9) do |t|
    if i * t == n
      puts 'Yes'
      exit
    end
  end
end
puts 'No'


# N, A, B = gets.split(" ").map(&:to_i)
# S = gets.chomp
N = gets.to_i

ok = false
(1..9).each do |x|
    (1..9).each do |y|
        if x*y == N
            ok = true
        end
    end
end

puts ok ? "Yes" : "No"


n = gets.to_i
(2..9).to_a.each do |num|
  if n % num == 0 && n / num < 10
    puts "Yes"
    exit
  end
end
puts "No"


n = gets.to_i
s = 0
(1..9).each do |x|
  if n%x==0
    if 1<=n%x && 9>=n%x
      s += 1
    end
  end
end
if s != 0
  puts "Yes"
else
  puts "No"
end


n = gets.chomp.to_i
arr = []
i = 1
while i <=9
    all = i ** 2
    arr << all
    i += 1
end

arr.each do |j|
    if j == n
        puts "Yes"
        exit
    end
end


/* {{{ */
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
/* }}} */

fn main() {
    input! {
        n: u32
    }
    for i in 1..10 {
        for j in 1..10 {
            if i * j == n {
                println!("Yes");
                return;
            }
        }
    }
    println!("No");
}
/* vim:set foldmethod=marker: */


use std::io::*;
use std::str::FromStr;

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("Failed to read bytes") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn main() {
    let n: usize = read();
    let mut ans = "No";
    'outer: for i in 1..10 {
        for j in 1..10 {
            if i * j == n {
                ans = "Yes";
                break 'outer;
            }
        }
    }
    println!("{}", ans);
}


use std::io;

fn procon_read<T: std::str::FromStr>() ->  Vec<T> {
	let mut buf = String::new();
	io::stdin().read_line(&mut buf).expect("");
	let iter = buf.split_whitespace();
	let mut v: Vec<T> = Vec::new();
	for i in iter {
		v.push(i.parse().ok().unwrap());
	}
	v
}

fn main() {
	let v:Vec<i32> = procon_read();
	let n = v[0];
	let mut flag = false;
	for i in 1..10 {
		for j in 1..10 {
			if i*j == n {
				flag = true;
				break;
			}
		}
	}
	if flag {
		println!("Yes");
	}else{
		println!("No");
	}
}


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input!{
        n: usize,
    };

    for i in 1..9{
        if n % i == 0 && n / i <= 9{
            println!("Yes");
            std::process::exit(0);
        }
    }
    println!("No");
}


#[allow(unused_imports)]
use std::cmp::max;
#[allow(unused_imports)]
use std::fmt;
#[allow(unused_imports)]
use std::fmt::Debug;
#[allow(unused_imports)]
use std::io;
#[allow(unused_imports)]
use std::str::FromStr;

fn main() {
    let n: i64 = get_vec_input()[0];
    let mut list: Vec<i64> = Vec::new();

    for i in 1..=9 {
        for j in 1..=9 {
            list.push(i * j);
        }
    }

    if list.contains(&n) {
        println!("Yes");
    } else {
        println!("No");
    }
}

#[allow(dead_code)]
fn sum_digit2(value: String) -> u32 {
    return value.chars().fold(0u32, |a, b| a + b.to_digit(10).unwrap());
}

#[allow(dead_code)]
fn sum_digit(value: i64) -> i64 {
    if value < 10 {
        return value;
    }
    return sum_digit(value / 10) + value % 10;
}

#[allow(dead_code)]
fn update_max<T>(left: &mut T, right: T)
where
    T: std::cmp::Ord + std::clone::Clone,
{
    if *left < right {
        *left = right.clone();
    }
}

#[allow(dead_code)]
fn update_min<T>(left: &mut T, right: T)
where
    T: std::cmp::Ord + std::clone::Clone,
{
    if *left > right {
        *left = right.clone();
    }
}

#[allow(dead_code)]
fn get_vec_input<T>() -> Vec<T>
where
    T: FromStr,
    T::Err: Debug,
{
    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");
    let vec: Vec<T> = input
        .split_whitespace()
        .map(|x| x.parse().unwrap())
        .collect();
    vec
}

#[allow(dead_code)]
fn get_tuple_input() -> (u64, f32) {
    let mut s = String::new();
    io::stdin().read_line(&mut s).expect("");
    let mut iter = s.trim().split_whitespace();
    let c: u64 = iter.next().unwrap().parse().unwrap();
    let n: f32 = iter.next().unwrap().parse().unwrap();
    (c, n)
}

#[allow(dead_code)]
fn get_string_input() -> String {
    let mut s = String::new();
    io::stdin().read_line(&mut s).expect("");
    s.trim().to_string()
}


#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

fn f(s: &[char]) -> bool {
    let m = s.len();
    for i in 0..m {
        if s[i] != s[m - 1 - i] {
            return false;
        }
    }
    true
}

use std::iter::Iterator;

fn main() {
    input! {
        n:usize,
    }

    let mut ans = false;

    for elem in 1..=9 {
        if n / elem < 10 {
            ans = true;
        }
    }

    if ans {
        println!("Yes")
    }else{
        println!("No")
    }

}


import Foundation

let input:String = readLine()!
let n = Int(input)!

let array = [11, 13, 17, 19, 22, 23, 26, 29, 31, 33, 34, 37, 38, 39, 41, 43, 44, 46, 47, 50, 51, 52, 53, 55, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
let answer = array.filter{ $0 == n }

if answer == [] {
  print("Yes")
} else {
  print("No")
}


let input_line = readLine()!.characters.split{$0==" "}.map { Int(String($0))! }
let n = input_line[0]
let canCalcTakahashi = !((1...9).map { n % $0 == 0 && n / $0 < 10 }.filter { $0 }.isEmpty)
print(canCalcTakahashi ? "Yes" : "No")


let n=Int(readLine()!)!
var judge=0
for i in 1...9{
  for j in 1...9{
    if i*j==n{
      judge=1
    }
  }
}
if judge==1 {
  print("Yes")
}else{
  print("No")
}


let n=Int(readLine()!)!
var judge=0
for i in 1...9{
  for j in 1...9{
    if i*j==n{
      judge=1
    }
  }
}
if judge==1 {
  print("Yes")
}else{
  print("N0")
}


var N = (Int)(readLine()!)!
var ans : String  = "No"
for i in 1 ... 9{
  for j in 1 ... 9{
    if i == j {
      ans = "Yes"
    }
  }
}

print(ans)


let input_line = readLine()!.characters.split{$0==" "}.map { Int(String($0))! }
let n = input_line[0]
var canCalcTakahashi = (1...9).map { n % $0 == 0 && n / $0 < 10 }.isEmpty
print(canCalcTakahashi ? "Yes" : "No")


function main(input: string[]): void {
    const n = shi(input);
    let res = false;
    for (let i = 1; i < 10; i++) {
        if (n % i == 0 && n / i < 10) {
            res = true;
            break;
        }
    }
    puts(res ? 'Yes' : 'No');

}

// === BEGIN MODULE ===
function shi(array: string[]): number {
    return parseInt(array.shift());
}
function shf(array: string[]): number {
    return parseFloat(array.shift());
}
function puts(...message: any[]): void {
    process.stdout.write(message.join(' ') + '\n');
}
// === END   MODULE ===

import { readFileSync } from 'fs';
if (process.argv[1] == __filename) {
    const path = process.argv[2] || '/dev/stdin';
    const input = readFileSync(path, 'utf-8');
    main(input.split(/\s+/));
}


export class Main {
  static main(input: string): string {
    const tmp: string[] = input.split("\n");
    const [n]: number[] = tmp.shift().split(" ").map(int => parseInt(int));
    for (let i = 1; i <= 9; i++) {
      if (n % i == 0) {
        let t = n / i;
        if (1 <= t && t <= 9) {
          return "Yes";
        }
      }
    }
    return `No`;
  }
}
console.log(Main.main(require("fs").readFileSync("/dev/stdin", "utf8")));


const fs = require('fs');
const input = fs.readFileSync('/dev/stdin', 'utf-8');
const N = parseInt(input);

for (let i = 1; i <= 9; ++i) {
  if (N % i !== 0) {
    continue;
  }
  if (N / i <= 9) {
    console.log('Yes');
    return;
  }
}

console.log('No');


'use strict'
function main(input: String) {
    console.log(parseInt(input, 10) <= 81 ? "Yes" : "No");
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function main(e){const r=parseInt(e),n=Math.sqrt(r);if(n>=10)return"No";if(Number.isInteger(n))return"Yes";const t=[];for(let e=2;e<r&&e<10;e++){r%e||t.push(e)}return t.some(e=>t.some(n=>{if(e*n===r)return!0}))?"Yes":"No"}console.log(main(require("fs").readFileSync("/dev/stdin","utf8")));


K = int(input())
start = 1

DP = [[1 for i in range(10)] for j in range(12)]

# 下からの桁数
for j in range(1, 12):
    # その位の数
    for i in range(10):
        DP[j][i] = DP[j-1][i]
        if i != 0:
            DP[j][i] += DP[j-1][i-1]
        if i != 9:
            DP[j][i] += DP[j-1][i+1]
s = 0
# 後ろから考える
res = ""
for j in range(12):
    for i in range(1, 10):
        prev = s
        s += DP[j][i]
        if s >= K:
            res += str(i)
            # print(i, j)
            break
    if s >= K:
        break

top = i
keta = j
sa = K - prev
for k in range(keta-1, -1, -1):
    t = 0
    for j in range(max(0, top-1), min(9, top+1)+1):
        # print("kj", k, j)
        t_prev = t
        t += DP[k][j]
        if t >= sa:
            res += str(j)
            sa -= t_prev
            top = j
            break
print(res)


K = int(input())

if K <= 9:
    print(K)
    exit()

memo = [[1]*10] + [[1]*10 for _ in range(9)]

n = 9
digit = 1
i = -1
ans = []
while True:
    i += 1
    if i == 10:
        i = 0
        digit += 1
    tmp = memo[digit-1][i]
    if i >= 1:
        tmp += memo[digit-1][i-1]
    if i <= 8:
        tmp += memo[digit-1][i+1]
    memo[digit][i] = tmp
    if i != 0:
        if n + tmp >= K:
            while digit >= 0:
                t = memo[digit][i]
                #if n + t == K:
                #    ans.append(i)
                #    for d in range(digit):
                #        ans.append(min(9, i+d))
                #    break
                if n + t >=  K:
                    ans.append(i)
                    digit -= 1
                    i = max(0, i-1)
                else:
                    n += t
                    i += 1
            break
        else:
            n += tmp

print(''.join(map(str, ans)))


def main():
    k = int(input())
    d = dict()

    # 2 ** 20 = 10 ** 6
    order = 0
    find = False
    for n_digit in range(1, 20):
        # print('(n_digit, order):', n_digit, order)
        if n_digit == 1:
            for i in range(10):
                d[(n_digit, i)] = 1

        else:
            for i in range(10):
                d[(n_digit, i)] = d[(n_digit - 1, i)]
                if i >= 1:
                    d[(n_digit, i)] += d[(n_digit - 1, i - 1)]
                if i <= 8:
                    d[(n_digit, i)] += d[(n_digit - 1, i + 1)]

        for i in range(1, 10):
            if order + d[(n_digit, i)] < k:
                order += d[(n_digit, i)]
            else:
                find = True

            if find:
                break

        if find:
            break

    # n_digit, start with i
    ans = list()
    ans.append(i)

    for digit in range(n_digit - 1, 0, -1):
        for j in range(i - 1, i + 2):
            if 0 <= j <= 9:
                if order + d[(digit, j)] < k:
                    order += d[(digit, j)]
                else:
                    ans.append(j)
                    i = j
                    break

    print(''.join(map(str, ans)))

main()


from collections import deque
K = int(input())
queue = deque([1,2,3,4,5,6,7,8,9])
count = 1
while count <= K:
  num = queue.popleft()
  if num%10!=0:
    queue.append(num*10+num%10-1)
  queue.append(num*10+num%10)
  if num%!=9:
    queue.append(num*10+num%10+1)

print(num)


from collections import deque

K = int(input())

count = 0
ans = 0
Q = deque([1,2,3,4,5,6,7,8,9])
while count != K:
  a = Q.popleft()
  b = a%10
  if b != 0:
    Q.append(q*10 + b - 1)
  Q.append(q*10)
  if b != 9:
    Q.append(q*10 + b + 1)
  count += 1
  ans = q
print(q)


from collections import deque

K = int(input())
q = deque([1, 2, 3, 4, 5, 6, 7, 8, 9])

for i in range(K):
    runrun = q.popleft()
    rem = runrun % 10
    if rem == 0:
        q.append(runrun * 10)
        q.append(runrun * 10 + rem + 1)
    elif rem == 9:
        q.append(runrun * 10 + rem - 1)
        q.append(runrun * 10)
    else:
        q.append(runrun * 10 + rem - 1)
        q.append(runrun * 10)
        q.append(runrun * 10 + rem + 1)

print(runrun)


import java.io.*;
import java.util.*;

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(br.readLine());
        if(k < 10)
            System.out.println(k);
        else {
            Sol sol = new Sol(k);
            sol.preComp();
        }
    }
}

class Sol {
    long[][] pre;
    int k, l;
    Stack<Integer> res;

    Sol(int k){
        this.k = k;
        this.l = 12;
        pre = new long[l][11];
        res = new Stack<>();
    }

    void preComp(){
       // base
       for(int dig = 0; dig < 10; ++dig){
           pre[1][dig] = 1;
       }
       pre[1][10] = 9;

       int stLen = 0;
       long globSum = 9;
       boolean esc = false;

       // rest
       for(int len = 2; len < l; ++len){
           for(int dig = 0; dig < 10; ++dig){
               for(int st = -1; st < 2; ++st){
                    int newDig= dig+st;
                    if(newDig < 0 || newDig > 9)
                        continue;
                    pre[len][dig] += pre[len-1][newDig];
               }
               long val = pre[len][dig];
               if(dig != 0){
                   globSum += val;
                   if(globSum >= k){
                       k -= (globSum-val);
                       stLen = len-1;
                       res.add(dig);
                       esc = true;
                       break;
                   }
               }
           }
           if(esc)
                break;
       }
        search(stLen,res.peek());
        StringBuilder sb = new StringBuilder();
        for(int el : res)
            sb.append(el);
        System.out.println(sb);
    }

    void search(int len, int currDig){
        if(len==0)
            return;

        if(k == 1 && currDig == 1){
            while(len-->0)
                res.add(0);
            return;
        }
        long tSum = 0;
        for(int st = -1; st < 2; ++st){
            int newDig = currDig+st;
            if(newDig < 0 || newDig > 9)
                continue;
            tSum += pre[len][newDig];
            if(tSum >= k){
                res.add(newDig);
                k -= (tSum - pre[len][newDig]);
                search(len-1, newDig);
                break;
            }
        }
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.IntStream;

public class Main {
	public static void main(String[] args) {
		Main main = new Main();
		main.solve();
	}

	private void solve() {
		Scanner sc = new Scanner(System.in);
		int K = sc.nextInt();
		if (K <= 12) {
			System.out.println(K);
			return;
		}
		int[][] dp = new int[12][10];
		for (int i = 0; i <= 9; i++) {
			dp[1][i] = 1;
		}
		for (int j = 2; j < 12; j++) {
			for (int i = 0; i <= 9; i++) {
				if (i - 1 >= 0) {
					dp[j][i] += dp[j - 1][i - 1];
				}
				dp[j][i] += dp[j - 1][i];
				if (i + 1 <= 9) {
					dp[j][i] += dp[j - 1][i + 1];
				}
			}
		}
		int sum = 0;
		for (int digit = 1; digit < 12; digit++) {
			for (int i = 1; i <= 9; i++) {
				sum += dp[digit][i];
				if (sum >= K) {
					System.out.println(dp_func(digit, i, K - (sum - dp[digit][i]), dp));
					return;
				}
			}
		}
	}

	String dp_func(int digit, int start, int rest, int[][] dp) {
		if (digit == 0) {
			return "";
		}
		if (start - 1 >= 0) {
			rest -= dp[digit - 1][start - 1];
			if (rest <= 0) {
				return start + dp_func(digit - 1, start - 1, rest + dp[digit - 1][start - 1], dp);
			}
		}
		rest -= dp[digit - 1][start];
		if (rest <= 0) {
			return start + dp_func(digit - 1, start, rest + dp[digit - 1][start], dp);
		}
		return start + dp_func(digit - 1, start + 1, rest, dp);
	}

	class Scanner {
		private InputStream in;
		private byte[] buffer = new byte[1024];
		private int index;
		private int length;

		public Scanner(InputStream in) {
			this.in = in;
		}

		private boolean isPrintableChar(int c) {
			return '!' <= c && c <= '~';
		}

		private boolean isDigit(int c) {
			return '0' <= c && c <= '9';
		}

		private boolean hasNextByte() {
			if (index < length) {
				return true;
			} else {
				try {
					length = in.read(buffer);
					index = 0;
				} catch (IOException e) {
					e.printStackTrace();
				}
				return length > 0;
			}
		}

		private boolean hasNext() {
			while (hasNextByte() && !isPrintableChar(buffer[index])) {
				index++;
			}
			return hasNextByte();
		}

		private int readByte() {
			return hasNextByte() ? buffer[index++] : -1;
		}

		public String next() {
			if (!hasNext()) {
				throw new RuntimeException("no input");
			}
			StringBuilder sb = new StringBuilder();
			int b = readByte();
			while (isPrintableChar(b)) {
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		public long nextLong() {
			if (!hasNext()) {
				throw new RuntimeException("no input");
			}
			long value = 0L;
			boolean minus = false;
			int b = readByte();
			if (b == '-') {
				minus = true;
				b = readByte();
			}
			while (isPrintableChar(b)) {
				if (isDigit(b)) {
					value = value * 10 + (b - '0');
				}
				b = readByte();
			}
			return minus ? -value : value;
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}
	}

	interface CombCalculator {
		long comb(int n, int m);
	}

	interface MobiusFunction {
		int get(int n);
	}

	/**
	 * メビウス関数をエラトステネスの篩っぽく前計算するクラスです。
	 * 計算量はO(1)で、前計算でO(N logN)です。
	 */
	class SieveMobiusFunction implements MobiusFunction {
		int size;
		int[] mobiusFunctionValues;

		public SieveMobiusFunction(int size) {
			this.size = size;
			mobiusFunctionValues = new int[size];

			mobiusFunctionValues[0] = 0;
			mobiusFunctionValues[1] = 1;
			for (int i = 2; i < size; i++) {
				mobiusFunctionValues[i] = 1;
			}
			for (int i = 2; i * i < size; i++) {
				for (int k = 1; i * i * k < size; k++) {
					mobiusFunctionValues[i * i * k] *= 0;
				}
			}

			for (int i = 2; i < size; i++) {
				if (mobiusFunctionValues[i] == 1) {
					for (int k = 1; i * k < size; k++) {
						mobiusFunctionValues[i * k] *= -2;
					}
				}
				if (mobiusFunctionValues[i] > 1) {
					mobiusFunctionValues[i] = 1;
				}
				if (mobiusFunctionValues[i] < -1) {
					mobiusFunctionValues[i] = -1;
				}
			}
		}

		@Override
		public int get(int n) {
			if (n > size) {
				throw new RuntimeException("n is greater than size.");
			}
			if (n < 0) {
				return 0;
			}
			return mobiusFunctionValues[n];
		}
	}

	/**
	 * メビウス関数を定義通り計算するクラスです。
	 * 計算量はO(logN)です。
	 */
	class PrimeFactorizationMobiusFunction implements MobiusFunction {
		@Override
		public int get(int n) {
			if (n <= 0) {
				return 0;
			}
			if (n == 1) {
				return 1;
			}
			int num = 0;
			for (int i = 2; i < n; i++) {
				if (n % i == 0) {
					n /= i;
					num++;
					if (n % i == 0) {
						return 0;
					}
				}
			}
			return num % 2 == 0 ? -1 : 1;
		}
	}

	/**
	 * 組み合わせ計算を階乗の値で行うクラスです(MOD対応)
	 * 階乗とその逆元は前計算してテーブルに格納します。
	 * C(N, N) % M の計算量は O(1)、 前計算でO(max(N, logM))です。
	 * sizeを1e8より大きい値で実行するとMLEの危険性があります。
	 * また素数以外のMODには対応していません(逆元の計算に素数の剰余環の性質を利用しているため)。
	 */
	class FactorialTableCombCalculator implements CombCalculator {
		int size;
		long[] factorialTable;
		long[] inverseFactorialTable;
		long mod;

		public FactorialTableCombCalculator(int size, long mod) {
			this.size = size;
			factorialTable = new long[size + 1];
			inverseFactorialTable = new long[size + 1];
			this.mod = mod;

			factorialTable[0] = 1L;
			for (int i = 1; i <= size; i++) {
				factorialTable[i] = (factorialTable[i - 1] * i) % mod;
			}
			inverseFactorialTable[size] = inverse(factorialTable[size], mod);
			for (int i = size - 1; i >= 0; i--) {
				inverseFactorialTable[i] = (inverseFactorialTable[i + 1] * (i + 1)) % mod;
			}
		}

		private long inverse(long n, long mod) {
			return pow(n, mod - 2, mod);
		}

		private long pow(long n, long p, long mod) {
			if (p == 0) {
				return 1L;
			}
			long half = pow(n, p / 2, mod);
			long ret = (half * half) % mod;
			if (p % 2 == 1) {
				ret = (ret * n) % mod;
			}
			return ret;
		}

		@Override
		public long comb(int n, int m) {
			if (n > size) {
				throw new RuntimeException("n is greater than size.");
			}
			if (n < 0 || m < 0 || n < m) {
				return 0L;
			}
			return (((factorialTable[n] * inverseFactorialTable[m]) % mod) * inverseFactorialTable[n - m]) % mod;
		}
	}

	/**
	 * 組み合わせ計算をテーブルで実装したクラスです(MOD対応)
	 * 前計算でO(N^2), combはO(1)で実行できます
	 * sizeを2 * 1e4より大きい値で実行するとMLEの危険性があります
	 */
	class TableCombCalculator implements CombCalculator {
		long[][] table;
		int size;

		public TableCombCalculator(int size, long mod) {
			this.size = size;
			table = new long[size + 1][];

			table[0] = new long[1];
			table[0][0] = 1L;
			for (int n = 1; n <= size; n++) {
				table[n] = new long[n + 1];
				table[n][0] = 1L;
				for (int m = 1; m < n; m++) {
					table[n][m] = (table[n - 1][m - 1] + table[n - 1][m]) % mod;
				}
				table[n][n] = 1L;
			}
		}

		@Override
		public long comb(int n, int m) {
			if (n > size) {
				throw new RuntimeException("n is greater than size.");
			}
			if (n < 0 || m < 0 || n < m) {
				return 0L;
			}
			return table[n][m];
		}
	}

	interface Graph {
		void link(int from, int to, long cost);
		Optional<Long> getCost(int from, int to);
		int getVertexNum();
	}

	interface FlowResolver {
		long maxFlow(int from, int to);
	}

	/**
	 * グラフの行列による実装
	 * 接点数の大きいグラフで使うとMLEで死にそう
	 */
	class ArrayGraph implements Graph {
		private Long[][] costArray;
		private int vertexNum;

		public ArrayGraph(int n) {
			costArray = new Long[n][];
			for (int i = 0; i < n; i++) {
				costArray[i] = new Long[n];
			}
			vertexNum = n;
		}

		@Override
		public void link(int from, int to, long cost) {
			costArray[from][to] = new Long(cost);
		}

		@Override
		public Optional<Long> getCost(int from, int to) {
			return Optional.ofNullable(costArray[from][to]);
		}

		@Override
		public int getVertexNum() {
			return vertexNum;
		}
	}

	/**
	 * DFS(深さ優先探索)による実装
	 * 計算量はO(E*MaxFlow)のはず (E:辺の数, MaxFlow:最大フロー)
	 */
	class DfsFlowResolver implements FlowResolver {
		private Graph graph;
		public DfsFlowResolver(Graph graph) {
			this.graph = graph;
		}

		/**
		 * 最大フロー(最小カット)を求める
		 * @param from 始点(source)のID
		 * @param to 終点(target)のID
		 * @return 最大フロー(最小カット)
		 */
		public long maxFlow(int from, int to) {
			long sum = 0L;
			long currentFlow;
			do {
				currentFlow = flow(from, to, Long.MAX_VALUE / 3, new boolean[graph.getVertexNum()]);
				sum += currentFlow;
			} while (currentFlow > 0);
			return sum;
		}

		/**
		 * フローの実行 グラフの更新も行う
		 * @param from 現在いる節点のID
		 * @param to 終点(target)のID
		 * @param current_flow ここまでの流量
		 * @param passed 既に通った節点か否かを格納した配列
		 * @return 終点(target)に流した流量/戻りのグラフの流量
		 */
		private long flow(int from, int to, long current_flow, boolean[] passed) {
			passed[from] = true;
			if (from == to) {
				return current_flow;
			}
			for (int id = 0; id < graph.getVertexNum(); id++) {
				if (passed[id]) {
					continue;
				}
				Optional<Long> cost = graph.getCost(from, id);
				if (cost.orElse(0L) > 0) {
					long nextFlow = current_flow < cost.get() ? current_flow : cost.get();
					long returnFlow = flow(id, to, nextFlow, passed);
					if (returnFlow > 0) {
						graph.link(from, id, cost.get() - returnFlow);
						graph.link(id, from, graph.getCost(id, from).orElse(0L) + returnFlow);
						return returnFlow;
					}
				}
			}
			return 0L;
		}
	}

	/**
	 * 1-indexedのBIT配列
	 */
	class BinaryIndexedTree {
		private long[] array;

		public BinaryIndexedTree(int size) {
			this.array = new long[size + 1];
		}

		/**
		 * 指定した要素に値を加算する
		 * 計算量はO(logN)
		 * @param index 加算する要素の添字
		 * @param value 加算する量
		 */
		public void add(int index, long value) {
			for (int i = index; i < array.length; i += (i & -i)) {
				array[i] += value;
			}
		}

		/**
		 * 1〜指定した要素までの和を取得する
		 * 計算量はO(logN)
		 * @param index 和の終端となる要素の添字
		 * @return 1〜indexまでの和
		 */
		public long getSum(int index) {
			long sum = 0L;
			for (int i = index; i > 0; i -= (i & -i)) {
				sum += array[i];
			}
			return sum;
		}
	}

	/**
	 * 1-indexedの2次元BIT配列
	 */
	class BinaryIndexedTree2D {
		private long[][] array;

		public BinaryIndexedTree2D(int size1, int size2) {
			this.array = new long[size1 + 1][];
			for (int i = 1; i <= size1; i++) {
				this.array[i] = new long[size2 + 1];
			}
		}

		/**
		 * 指定した要素に値を加算する
		 * 計算量はO(logN * logN)
		 * @param index1 加算する要素の1次元目の添字
		 * @param index2 加算する要素の2次元目の添字
		 * @param value 加算する量
		 */
		public void add(int index1, int index2, long value) {
			for (int i1 = index1; i1 < array.length; i1 += (i1 & -i1)) {
				for (int i2 = index2; i2 < array.length; i2 += (i2 & -i2)) {
					array[i1][i2] += value;
				}
			}
		}

		/**
		 * (1,1)〜指定した要素までの矩形和を取得する
		 * 計算量はO(logN * logN)
		 * @param index1 和の終端となる要素の1次元目の添字
		 * @param index2 和の終端となる要素の2次元目の添字
		 * @return (1,1)〜(index1,index2)までの矩形和
		 */
		public long getSum(int index1, int index2) {
			long sum = 0L;
			for (int i1 = index1; i1 > 0; i1 -= (i1 & -i1)) {
				for (int i2 = index2; i2 > 0; i2 -= (i2 & -i2)) {
					sum += array[i1][i2];
				}
			}
			return sum;
		}
	}

	interface UnionFind {
		void union(int A, int B);
		boolean judge(int A, int B);
		Set<Integer> getSet(int id);
	}

	/**
	 * ArrayUnionFindの拡張
	 * MapSetで根の添字から根にぶら下がる頂点の集合が取得できるようにした
	 * getSetメソッドをO(logN * logN)に落とせているはず
	 * ただしunionメソッドは2倍の計算量になっているので注意(オーダーは変わらないはず)
	 */
	class SetUnionFind extends ArrayUnionFind {
		Map<Integer, Set<Integer>> map;
		public SetUnionFind(int size) {
			super(size);
			map = new HashMap<>();
			for (int i = 0; i < size; i++) {
				map.put(i, new HashSet<>());
				map.get(i).add(i);
			}
		}

		@Override
		protected void unionTo(int source, int dest) {
			super.unionTo(source, dest);
			map.get(dest).addAll(map.get(source));
		}

		@Override
		public Set<Integer> getSet(int id) {
			return map.get(root(id));
		}
	}

	/**
	 * 配列によるUnionFindの実装
	 * getSetメソッドはO(NlogN)なのでTLEに注意
	 */
	class ArrayUnionFind implements UnionFind {
		int[] parent;
		int[] rank;
		int size;
		public ArrayUnionFind(int size) {
			parent = new int[size];
			for (int i = 0; i < size; i++) {
				parent[i] = i;
			}
			rank = new int[size];
			this.size = size;
		}

		@Override
		public void union(int A, int B) {
			int rootA = root(A);
			int rootB = root(B);
			if (rootA != rootB) {
				if (rank[rootA] < rank[rootB]) {
					unionTo(rootA, rootB);
				} else {
					unionTo(rootB, rootA);
					if (rank[rootA] == rank[rootB]) {
						rank[rootA]++;
					}
				}
			}
		}

		protected void unionTo(int source, int dest) {
			parent[source] = dest;
		}

		@Override
		public boolean judge(int A, int B) {
			return root(A) == root(B);
		}

		@Override
		public Set<Integer> getSet(int id) {
			Set<Integer> set = new HashSet<>();
			IntStream.range(0, size).filter(i -> judge(i, id)).forEach(set::add);
			return set;
		}

		protected int root(int id) {
			if (parent[id] == id) {
				return id;
			}
			parent[id] = root(parent[id]);
			return parent[id];
		}
	}

	/**
	 * 素数のユーティリティ
	 */
	class PrimeNumberUtils {
		boolean[] isPrimeArray;
		List<Integer> primes;

		/**
		 * 素数判定の上限となる値を指定してユーティリティを初期化
		 * @param limit 素数判定の上限(この値以上が素数であるか判定しない)
		 */
		public PrimeNumberUtils(int limit) {
			if (limit > 10000000) {
				System.err.println("上限の値が高すぎるため素数ユーティリティの初期化でTLEする可能性が大変高いです");
			}
			primes = new ArrayList<>();
			isPrimeArray = new boolean[limit];
			if (limit > 2) {
				primes.add(2);
				isPrimeArray[2] = true;
			}

			for (int i = 3; i < limit; i += 2) {
				if (isPrime(i, primes)) {
					primes.add(i);
					isPrimeArray[i] = true;
				}
			}
		}

		public List<Integer> getPrimeNumberList() {
			return primes;
		}

		public boolean isPrime(int n) {
			return isPrimeArray[n];
		}

		private boolean isPrime(int n, List<Integer> primes) {
			for (int prime : primes) {
				if (n % prime == 0) {
					return false;
				}
				if (prime > Math.sqrt(n)) {
					break;
				}
			}
			return true;
		}
	}

	interface BitSet {
		void set(int index, boolean bit);
		boolean get(int index);
		void shiftRight(int num);
		void shiftLeft(int num);
		void or(BitSet bitset);
		void and(BitSet bitset);
	}

	/**
	 * Longの配列によるBitSetの実装
	 * get/setはO(1)
	 * shift/or/andはO(size / 64)
	 */
	class LongBit implements BitSet {
		long[] bitArray;

		public LongBit(int size) {
			bitArray = new long[((size + 63) / 64)];
		}

		@Override
		public void set(int index, boolean bit) {
			int segment = index / 64;
			int inIndex = index % 64;
			if (bit) {
				bitArray[segment] |= 1L << inIndex;
			} else {
				bitArray[segment] &= ~(1L << inIndex);
			}
		}

		@Override
		public boolean get(int index) {
			int segment = index / 64;
			int inIndex = index % 64;
			return (bitArray[segment] & (1L << inIndex)) != 0L;
		}

		@Override
		public void shiftRight(int num) {
			int shiftSeg = num / 64;
			int shiftInI = num % 64;
			for (int segment = 0; segment < bitArray.length; segment++) {
				int sourceSeg = segment + shiftSeg;
				if (sourceSeg < bitArray.length) {
					bitArray[segment] = bitArray[sourceSeg] >>> shiftInI;
					if (shiftInI > 0 && sourceSeg + 1 < bitArray.length) {
						bitArray[segment] |= bitArray[sourceSeg + 1] << (64 - shiftInI);
					}
				} else {
					bitArray[segment] = 0L;
				}
			}
		}

		@Override
		public void shiftLeft(int num) {
			int shiftSeg = num / 64;
			int shiftInI = num % 64;
			for (int segment = bitArray.length - 1; segment >= 0; segment--) {
				int sourceSeg = segment - shiftSeg;
				if (sourceSeg >= 0) {
					bitArray[segment] = bitArray[sourceSeg] << shiftInI;
					if (shiftInI > 0 && sourceSeg > 0) {
						bitArray[segment] |= bitArray[sourceSeg - 1] >>> (64 - shiftInI);
					}
				} else {
					bitArray[segment] = 0L;
				}
			}
		}

		public long getLong(int segment) {
			return bitArray[segment];
		}

		@Override
		public void or(BitSet bitset) {
			if (!(bitset instanceof LongBit)) {
				return;
			}
			for (int segment = 0; segment < bitArray.length; segment++) {
				bitArray[segment] |= ((LongBit)bitset).getLong(segment);
			}
		}

		@Override
		public void and(BitSet bitset) {
			if (!(bitset instanceof LongBit)) {
				return;
			}
			for (int segment = 0; segment < bitArray.length; segment++) {
				bitArray[segment] &= ((LongBit)bitset).getLong(segment);
			}
		}
	}

}


import java.io.*;
import java.util.*;
public class Main {
    static long[][][]memo;
    static long dp(int one,int pre,int idx){
        if (pre<0||pre>9)
            return 0;
        if (idx==10)
            return one;
        if (memo[one][pre][idx]!=-1){
            return memo[one][pre][idx];
        }
        if (one==0){
            long ans= dp(0,0,idx+1);
            for (int i =1;i<10;i++)
                ans+=dp(1,i,idx+1);
            return memo[one][pre][idx]=ans;
        }
        int nxt1=pre+1;
        int nxt2=pre-1;
        long ans=dp(one,pre,idx+1)+dp(1,nxt1,idx+1);
        if (nxt2>0) {
            ans += dp(1, nxt2, idx + 1);
        }
        else ans+=dp(one,nxt2,idx+1);
        return memo[one][pre][idx]=ans;
    }
    static  long c,k;
    static void trace(int one,int pre,int idx){
        if (idx==10)
            return;

        if (one==0){
             long x = dp(0,0,idx+1);
             if (c+x>=k){
                 trace(0,0,idx+1);
                 return;
             }
             c+=x;
            for (int i =1;i<10;i++) {
                x = dp(1, i, idx + 1);
                if (c+x>=k){
                    System.out.print(i);
                    trace(1,i,idx+1);
                    return;
                }
                c+=x;
            }
            return;
        }
        for (int j=-1;j<2;j++){
            int f= pre+j;
            if (pre+j<0)continue;
            long x=dp(one,pre+j,idx+1);
            if (x+c>=k){
                System.out.print(pre+j);
                trace(one,pre+j,idx+1);
                return;
            }
            c+=x;
        }
    }
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        k = sc.nextInt();
        StringBuilder sol= new StringBuilder();
        memo= new long[2][10][10];
        for (long[][]z:memo)for (long[]x:z)Arrays.fill(x,-1);
        trace(0,0,0);
        pw.flush();
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public double nextDouble() throws IOException {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if (x.charAt(0) == '-') {
                neg = true;
                start++;
            }
            for (int i = start; i < x.length(); i++)
                if (x.charAt(i) == '.') {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                } else {
                    sb.append(x.charAt(i));
                    if (dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg ? -1 : 1);
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;

public class Main {
	public static void main(String[] args) {
		new Main().solve();
		pw.close();
	}

	/**
	 * ASCII
	 * 0 48
	 * A 65
	 * a 97
	 */

	static PrintWriter pw = new PrintWriter(System.out);

	long MOD = 1_000_000_007;

	void solve() {
		FastScanner sc = new FastScanner();
		int K = sc.nextInt();
		Lunlun l = new Lunlun();
		out(l.get(K));
		//for (int i = 100; i <= 1000; i++) out(l.get(i));
	}

	boolean func(char[] ary) {
		for (int i = 0; i < ary.length; i++) {
			if (ary[i] != ary[ary.length-1-i]) return false;
		}
		return true;
	}

	double getD(double x1, double x2, double y1, double y2) {
		return Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2, 2));
	}

	int[][] d4 = new int[][] {{1,0},{0,1},{-1,0},{0,-1}};
	int[][] d8 = new int[][] {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

	class Data {
		int a;
		int b;
		int c;
		Data(){}
		Data(int a) {
			this.a = a;
		}
		Data(int a, int b, int c) {
			this.a = a;
			this.b = b;
			this.c = c;
		}
		Data(int a, int b) {
			this.a = a;
			this.b = b;
		}
	}

	class Lunlun {
		int[] num = new int[20];
		int count = 0;
		int max = 0;
		int pointer = 0;

		public void next() {
			if (pointer == max) {
				if (num[pointer] < 9) {
					int t = ++num[pointer];
					count++;
					for (int i = 0; i < pointer; i++) {
						num[i] = t-1;
					}
					pointer = 0;
				} else {
					max++;
					num[max] = 1;
					for (int i = 0; i < max; i++) num[i] = 0;
					pointer = 0;
					count++;
				}
			} else {
				if (num[pointer] <= num[pointer+1] && num[pointer] != 9) {
					int t = ++num[pointer];
					count++;
					for (int i = 0; i < pointer; i++) {
						num[i] = t-1;
					}
					pointer = 0;
				} else {
					pointer++;
					next();
				}
			}
		}

		public long get(int c) {
			while (c != count) {
				next();
			}
			StringBuilder sb = new StringBuilder();
			for (int i : num) sb.append(i);
			sb.reverse();
			return Long.parseLong(sb.toString());
		}
	}

	class Permutation {
		int[] array;

		Permutation(int N) {
			array = new int[N];
			for (int i = 0; i < N; i++) {
				array[i] = i+1;
			}
		}

		boolean nextPermutation() {
		    int i = array.length - 1;
		    while (i > 0 && array[i - 1] >= array[i])
		        i--;
		    if (i <= 0)
		        return false;

		    int j = array.length - 1;
		    while (array[j] <= array[i - 1])
		        j--;
		    int temp = array[i - 1];
		    array[i - 1] = array[j];
		    array[j] = temp;

		    j = array.length - 1;
		    while (i < j) {
		        temp = array[i];
		        array[i] = array[j];
		        array[j] = temp;
		        i++;
		        j--;
		    }
		    return true;
		}
	}

	class UnionFind {
		int[] parents;
		int[] counts;

		public UnionFind(int size) {
			parents = new int[size];
			counts = new int[size];
			for (int i = 0; i < size; i++) {
				parents[i] = i;
				counts[i] = 1;
			}
		}

		public int find(int a) {
			if (parents[a] == a) return a;
			parents[a] = find(parents[a]);
			return parents[a];
		}

		public void unite(int a, int b) {
			a = find(a);
			b = find(b);
			if (a == b) return;
			if (counts[a] < counts[b]) {
				parents[a] = b;
				counts[b] += counts[a];
			} else {
				parents[b] = a;
				counts[a] += counts[b];
			}
		}

		public boolean differ(int a, int b) {
			a = find(a);
			b = find(b);
			return a != b;
		}

		public int count(int a) {
			return counts[find(a)];
		}
	}

	class Combination {
		final int mod;
		final int max;

		final long[] fact;
		final long[] inv;
		final long[] invfact;

		public Combination(int n) {
			this(n, 1_000_000_007);
		}

		public Combination(int n, int mod) {
			this.mod = mod;
			max = n + 1;
			fact = new long[max];
			invfact = new long[max];
			inv = new long[max];

			inv[1] = 1;
			for (int i = 2; i < inv.length; i++) {
				inv[i] = inv[mod % i] * (mod - mod / i) % mod;
			}

			fact[0] = 1;
			invfact[0] = 1;
			for (int i = 1; i < inv.length; i++) {
				fact[i] = i * fact[i - 1] % mod;
				invfact[i] = inv[i] * invfact[i - 1] % mod;
			}
		}

		public long get(int n, int r) {
			return fact[n] * invfact[n - r] % mod * invfact[r] % mod;
		}

		public long gcd(long a, long b) {
			if (b == 0) return a;
			else {
				b %= MOD;
				if (b < 0) b+=MOD;
				return gcd(b, (b-a*inv[(int)b]%MOD*b%MOD)%MOD);
			}
		}
	}

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

	public long getInv(long a) {
		long b = MOD, u = 1, v = 0;
		while (b > 0) {
			long t = a / b;
			a -= t * b;
			long tmp = a;
			a = b;
			b = tmp;
			u -= t * v;
			tmp = u;
			u = v;
			v = tmp;
		}
		u %= MOD;
		if (u < 0) u += MOD;
		return u;
	}

	public long modPow(long n) {
		if (n == 0) return 1;
		long x = modPow(n / 2);
		x *= x;
		x %= MOD;
		if (n % 2 == 1) x *= 2;
		x %= MOD;
		return x;
	}

	public long choose(long n, long m) {
		long deno = 1;
		long nume = 1;
		m = (n - m < m ? n - m : m);
		for (long i = 1; i <= m; i++) {
			deno = deno * (n - i + 1) % MOD;
			nume = nume * i % MOD;
		}
		return deno * getInv(nume) % MOD;
	}

	public void reverse(int[] a) {
		int last = a.length-1;
		int n = a.length / 2;
		for (int i = 0; i < n; i++) {
			int t = a[i];
			a[i] = a[last-i];
			a[last-i] = t;
		}
	}

	public void reverse(long[] a) {
		int last = a.length-1;
		int n = a.length / 2;
		for (int i = 0; i < n; i++) {
			long t = a[i];
			a[i] = a[last-i];
			a[last-i] = t;
		}
	}

	void fout(Object... args) {
		StringBuilder sb = new StringBuilder();
		for (Object arg : args) {
			sb.append(arg.toString());
			sb.append(" ");
		}
		out(sb.toString());
	}

	void out() {
		pw.println();
	}

	void out(String a) {
		pw.println(a);
	}
	void out(boolean a) {
		pw.println(a);
	}

	void out(int a) {
		pw.println(a);
	}

	void out(long a) {
		pw.println(a);
	}

	void out(double a) {
		pw.println(a);
	}

	void out(char a) {
		pw.println(a);
	}

	void rout(String a) {
		out(a);
		pw.close();
		System.exit(0);
	}
	void rout(int a) {
		out(a);
		pw.close();
		System.exit(0);
	}
	void rout(long a) {
		out(a);
		pw.close();
		System.exit(0);
	}
	void rout(double a) {
		out(a);
		pw.close();
		System.exit(0);
	}
	void rout(char a) {
		out(a);
		pw.close();
		System.exit(0);
	}
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        } else {
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }

    private int readByte() {
        if (hasNextByte())
            return buffer[ptr++];
        else
            return -1;
    }

    private boolean isPrintableChar(int c) {
        return 33 <= c && c <= 126;
    }

    public boolean hasNext() {
        while (hasNextByte() && !isPrintableChar(buffer[ptr]))
            ptr++;
        return hasNextByte();
    }

    public String next() {
        if (!hasNext())
            throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while (isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    public long nextLong() {
        if (!hasNext())
            throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while (true) {
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            } else if (b == -1 || !isPrintableChar(b)) {
                return minus ? -n : n;
            } else {
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }

    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE)
            throw new NumberFormatException();
        return (int) nl;
    }

    public double nextDouble() {
        return Double.parseDouble(next());
    }
}


import java.util.*;
import java.io.*;

public class Main {
    static StringTokenizer st;
    static BufferedReader br;
    static PrintWriter out;

    // this should be DP Frog.
    // we aslo can use queue
    // Lunlun Number abcde
    // we can build from abcd

    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));

        // useQueue();
        useDP();
    }
    public static void useDP() throws IOException {
        int K = nextInt();

        long dp[] = new long[3*K+1]; //max

        for (int x=1; x<10; x++) {
            dp[x] = x;
        }

        int index = 10;
        for (int x=1; x<=K; x++) {
            long cur = dp[x];
            long mod = cur % 10;
            if(mod != 0){
                dp[index] = 10*cur+mod-1;
                index++;
                if(index>K){break;}
            }
            dp[index] = 10*cur+mod;
            index++;
            if(index>K){break;}
            if(mod != 9){
                dp[index] = 10*cur+mod+1;
                index++;
                if(index>K){break;}
            }
        }

        System.out.println(dp[K]);
    }

    public static void useQueue() throws IOException {
        int K = nextInt();

        LinkedList<Long> queue = new LinkedList<Long>();

        for (int x=1; x<10; x++) {
            queue.add((long)x);
        }

        for (int x=1; x<K; x++) {
            long cur = queue.poll();
            long mod = cur % 10;
            if(mod != 0){
                queue.add(10*cur+mod-1);
            }
            queue.add(10*cur+mod);
            if(mod != 9){
                queue.add(10*cur+mod+1);
            }
        }

        System.out.println(queue.poll());
    }

    public static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }
    public static long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    public static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    static String next() throws IOException {
        while (st == null || !st.hasMoreTokens())
            st = new StringTokenizer(br.readLine().trim());
        return st.nextToken();
    }
}


import java.util.*;
import java.io.*;

public class Main {

	public static void solve(InputReader in) {
		int n = in.readInt();
		Queue<Long> q = new LinkedList<>();
		ArrayList<Long> list = new ArrayList<>();
		for(int i = 1; i<=9; i++) {
			q.add(i);
			list.add(i);
		}

		for(int i = 0; true; i++) {
		   int x = q.poll();
		   int y = 0;
		   if(x % 10 != 0) {
			   y = 10 * x + (x%10) -1;
			   q.add(y);
			   list.add(y);
		   }
		   y = 10*x + (x%10);
		   q.add(y);
		   list.add(y);

		   if(x % 10 != 9) {
			   y = 10*x + (x%10) + 1;
			   q.add(y);
			   list.add(y);
		   }

		   if(n <= q.size()) {
			   System.out.println(list.get(n-1));
			   return;
		   }
		}
	}

    public static void main(String[] args) {
    	InputReader in = new InputReader(System.in);
    	int t = 1;
    	while(t-- > 0) {
    		solve(in);
    	}
    }
}

class InputReader{
	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	 public InputReader(InputStream stream) {
		this.stream = stream;
	}

     public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

     public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

     public String readString() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

     public long readLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			if (c < '0' || c > '9') {
				throw new InputMismatchException();
			}
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

     public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

     public String next() {
		return readString();
	}

     public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}


#include <cstdio>

int n;
int f[15][15];

int main() {
    scanf("%d", &n);
    for (int i = 0; i <= 9; ++i) f[1][i] = 1;
    for (int i = 2; i <= 10; ++i)
        for (int j = 0; j <= 9; ++j) {
            if (!j) f[i][j] = f[i - 1][0] + f[i - 1][1];
            else if (j == 9) f[i][j] = f[i - 1][8] + f[i - 1][9];
            else f[i][j] = f[i - 1][j - 1] + f[i - 1][j] + f[i - 1][j + 1];
        }
    int sum = 0, ok = 0, cnt, now;
    for (int i = 1; i <= 10; ++i) {
        for (int j = 1; j <= 9; ++j) {
            if (sum + f[i][j] >= n) {
                printf("%d", j);
                n -= sum;
                now = j;
                ok = 1;
            }
            if (ok) break;
            sum += f[i][j];
        }
        if (ok) {
            cnt = i;
            break;
        }
    }
    for (int i = cnt - 1; i; --i) {
        sum = 0;
        if (now) {
            if (sum + f[i][now - 1] >= n) {
                printf("%d", --now);
                n -= sum;
                continue;
            }
            sum += f[i][now - 1];
        }
        if (sum  + f[i][now] >= n) {
            printf("%d", now);
            n -= sum;
            continue;
        }
        sum += f[i][now];
        if (now != 9) {
            if (sum + f[i][now + 1] >= n) {
                printf("%d", ++now);
                n -= sum;
                continue;
            }
            sum += f[i][now + 1];
        }
    }
    return 0;
}


#include<bits/stdc++.h>
#define int long long int
#define ld long double
#define getFaster ios_base::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define rep(i,init,n) for(int i=init;i<n;i++)
#define rev(i,n,init) for(int i=n;i>=init;i--)
#define MAXN 200005
#define MOD2 998244353
#define MOD1 1e9+7
#define f first
#define s second
#define endl '\n'
#define pii pair<int,int>
#define piii pair<pii,int>
#define precise(i) cout<<fixed<<setprecision(i)
using namespace std;
const long double PI = atan(1.0)*4;
const int64_t INF=1000000000000000003;
const int32_t LOG=21;
const int MOD=MOD2;
int dp[30][10];
int ans[200005];
vector<int> v[10];
int32_t main()
{
      getFaster;
      int tests=1;
      //cin>>tests;
      rep(ii,0,tests)
      {
           int k;
           cin>>k;
           int k1=k;
           rep(i,0,10)dp[1][i]=1;
            rep(i,0,10)
            {
                  if(i-1>=0)v[i].push_back(i-1);
                  v[i].push_back(i);
                  if(i+1<10)v[i].push_back(i+1);
            }

           rep(i,2,30)
           {
                 rep(j,0,10)
                 {
                      if(j==0)
                      {
                          dp[i][j]=dp[i-1][0]+dp[i-1][1];
                      }
                      else if(j==9)
                      {
                          dp[i][j]=dp[i-1][8]+dp[i-1][9];
                      }
                      else
                      {
                          dp[i][j]=dp[i-1][j]+dp[i-1][j+1]+dp[i-1][j-1];
                      }
                 }
           }

           int start=-1;

           rep(i,1,15)
           {
               int tot=0;
               rep(j,1,10)tot+=dp[i][j];
               if(tot<k)
               {
                    k-=tot;
                    continue;
               }
               else
               {
                   start=i;
                   break;
               }
           }

           int prev=-1;
           rev(i,start,1)
           {

                 if(prev==-1)
                 {
                     int tot=0;
                     rep(j,1,10)
                     {
                         tot=dp[i][j];
                         if(tot<k)
                         {
                             k-=tot;
                             continue;
                         }
                         else
                         {
                              ans[i]=j;
                              prev=j;
                              break;
                         }
                     }
                 }
                 else
                 {
                       int tot=0;
                       for(auto it:v[prev])
                       {
                            tot=dp[i][it];
                            if(tot<k)
                            {
                               k-=tot;
                               continue;
                            }
                            else
                            {
                                ans[i]=it;
                                prev=it;
                                break;
                            }
                       }
                 }
           }
           reverse(ans+1,ans+start+1);
           rep(i,1,start+1)cout<<ans[i];
           cout<<endl;

      }
      return 0;
}

/*
 TIPS(FOR ME):
 1.) Check for corner cases (like 0 is exception case)
 2.) Check for global memory sizes,memory refreshments and its complexity
 3.) Check for sorting criteria (if used 1-based indexing)
 4.) Check for numbers overflow (while multiplying and doing MOD)
 5.) Check for typecasting issues like int to float( while dividing numbers)
*/


#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
inline int read(){
	char c=getchar();int t=0,f=1;
	while((!isdigit(c))&&(c!=EOF)){if(c=='-')f=-1;c=getchar();}
	while((isdigit(c))&&(c!=EOF)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int f[15][10][10],k,out[15],sum[15],pre[15][11];
signed main(){
	k=read();
	for(int i=0;i<=9;i++){
		f[1][i][i]=1;
		pre[1][i]=1;
	}
	sum[1]=9;
	for(int i=2;i<=11;i++){
		for(int j=0;j<=9;j++){
			for(int k=0;k<=9;k++){
				if(k>0)
				f[i][j][k]+=f[i-1][j][k-1];
				if(k<9)
				f[i][j][k]+=f[i-1][j][k+1];
				f[i][j][k]+=f[i-1][j][k];
				pre[i][j]+=f[i][j][k];
			}
			if(j!=0)
			sum[i]+=pre[i][j];
		}
		sum[i]+=sum[i-1];
		//printf("%d %d\n",sum[i],i);
	}
	for(int i=11;i>=1;i--){
		if(sum[i-1]>=k){
			continue;
		}
		k=k-sum[i-1];
		int alfa=0;
		for(int j=1;j<=9;j++){
			alfa+=pre[i][j];
			if(alfa>=k){
				alfa=alfa-pre[i][j];
				k=k-alfa;
				//printf("%d\n",k);
				out[i]=j;
				int len=i-1;
				while(len){
					alfa=0;
					//printf("%d %d\n",max(out[len+1]-1,0),min(out[len+1]+1,9));
					for(int v=max(out[len+1]-1,0);v<=min(out[len+1]+1,9);v++){
						alfa+=pre[len][v];
						if(k<=alfa){
							alfa-=pre[len][v];
							out[len]=v;
							k-=alfa;
							break;
						}
					}
					//printf("%d %d\n",k,alfa);
					len--;
				}
				break;
			}
		}
		break;
	}
	int flag=1;
	for(int i=10;i>=1;i--){
		if(flag&&(!out[i]))continue;
		flag=0;
		printf("%d",out[i]);
	}
	puts("");
	return 0;
}


#include<bits/stdc++.h>

typedef long long ll;
typedef std::pair<ll, ll> P;
typedef std::tuple<ll, ll, ll> t3;
constexpr ll INF = 1e15;
constexpr ll mod = 1e9+7;

#define rep(i,n) for(int i = 0; i < int(n); i++)
using namespace std;

template<class T> inline bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }

class Divisor {
private:
	vector<ll> F;
public:
	Divisor(ll N) {
		for (ll i = 1; i * i <= N; i++) {
			if (N % i == 0) {
				F.push_back(i);
				if (i * i != N) F.push_back(N / i);
			}
		}
		sort(begin(F), end(F));
	}
	int size() { return F.size(); }
	ll operator[](int k) { return F[k]; }
	const vector<ll>& factors() { return F; }
};

int main() {
	ll k;
	cin >> k;
	vector<vector<ll>> dp(k, vector<ll>(10, 0));
	rep(i, 10) {
		dp[k - 1][i] = 1;
	}
	for (int i = k - 2; i >= 0; i--) {
		rep(j, 10) {
			for (int a : {-1, 0, 1}) {
				ll id = a + j;
				if (id < 0 || id > 9) continue;
				dp[i][j] += dp[i + 1][id];
				chmin(dp[i][j], INF);
			}
		}
	}
	vector<int> ans;
	int front = -1;
	ll prev = 0;
	int digit = 1;
	for (; digit < k; digit++) {
		for (int j = 1; j < 10; j++) {
			ll next = dp[k - digit][j];
			if (prev + next >= k) {
				ans.push_back(j);
				front = j;
				break;
			}
			prev += next;
		}
		if (front >= 0) break;
	}
	for (int i = k - digit + 1; i < k; i++) {
		for (int a : {-1, 0, 1}) {
			ll j = a + front;
			if (j < 0 || j > 9) continue;
			ll next = dp[i][j];
			if (prev + next >= k) {
				ans.push_back(j);
				front = j;
				break;
			}
			prev += next;
		}
	}
	bool init = false;
	for (int i = 0; i < ans.size(); i++) {
		if (ans[i] != 0) {
			init = true;
			cout << ans[i];
		}
		else {
			if (init) {
				cout << ans[i];
			}
		}
	}
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

#define ll long long
#define ii pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define ff first
#define ss second
#define pi 3.14159265
#define oo 1000000007
#define loo 0x7fffffffffffffff

#define prime 1000000007
#define mod 1000000007
ll powmod(ll a,ll b) {ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define W(x) cerr << "\033[31m" << #x << " = " << x << "\033[0m" << "\n";
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    vector<ll> v {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int k; cin >> k;
    int at = 0;
    while((int)v.size() < k){
        vl aux;
        for(int i = at; i < (int)v.size(); i++){
            ll l = v[i];
            if(l%10LL == 0LL){
                aux.pb(l*10LL+1LL);
                if((int)v.size()+(int)aux.size() == k) break;
                aux.pb(l*10LL);
                if((int)v.size()+(int)aux.size() == k) break;
            }
            else if(l%10LL == 9){
                aux.pb(l*10LL+8);
                if((int)v.size()+(int)aux.size() == k) break;
                aux.pb(l*10LL+9);
                if((int)v.size()+(int)aux.size() == k) break;
            }
            else{
                aux.pb(l*10LL+(l%10LL-1));
                if((int)v.size()+(int)aux.size() == k) break;
                aux.pb(l*10LL+(l%10LL));
                if((int)v.size()+(int)aux.size() == k) break;
                aux.pb(l*10LL+(l%10LL+1));
                if((int)v.size()+(int)aux.size() == k) break;
            }
        }
        at = (int)v.size();
        for(auto l : aux){
            v.pb(l);
        }
        sort(v.begin(), v.end());
    }

    cout << v[k-1] << "\n";

    return 0;
}


#include <bits/stdc++.h>
#define ss second
#define ff first
#define all(x) x.begin(), x.end()

// #define DEBUG 100

using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll >;

const ll oo = 1e18 + 7;
const ll mod = 1e9 + 7,maxn = 1e5 + 100, maxm = 1e5+100;
const double PI = acos(-1);
vector<ll> primo;
bitset<maxn> np(0);

bool che(string s){
    for (int i=0; i<(int)s.size() - 1; i++){
        if (abs(s[i] - s[i+1]) > 1) return false;
    }
    return true;
}

int main (){
    ios_base::sync_with_stdio(false);
    int n, i = 1;
    cin >> n;

    vector<string> vs;
    while ((int) vs.size() < n){
        string s = to_string(i);
        if (che(s)) vs.push_back(s);
        i++;
    }

    cout << vs.back() << endl;
    return 0;
}


#include<stdio.h>
int k,i,e=10;
long long r[100001];
int main(){
    scanf("%d",&k);
    for(i=1;i<10;i++)r[i]=i;
    for(i=1;i<k;i++){
        if(e>100000)continue;
        if(r[i]%10!=0){
            r[e]=10*r[i]+r[i]%10-1;
            e++;
        }
        r[e]=10*r[i]+r[i]%10;
        e++;
        if(r[i]%10!=9){
            r[e]=10*r[i]+r[i]%10+1;
            e++;
        }
    }
    printf("%lld",r[i]);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
typedef long long ll;

int main(void){
  ll K,n=100000,ans=0;
  scanf("%lld",&K);
  ll q[n];
  for(ll i=0;i<=8;i++) q[i]=i+1;
  ll head=0,tail=8,tmp=0,flag=0;
  while(K>0){
    ans=q[head];
    head=(head+1)%n;
    tmp=ans%10;
    if(flag==0){
    if(tmp>0){
      tail=(tail+1)%n;
      q[tail]=10*ans+tmp-1;
    }
    tail=(tail+1)%n;
    q[tail]=10*ans+tmp;
    if(tmp<9){
      tail=(tail+1)%n;
      q[tail]=10*ans+tmp+1;
    }
    if(tail<8) flag=1;
    }
    K--;
  }
  printf("%lld",ans);

}


#include <stdio.h>
#define true 1
#define false 0

int loop(long int a);
int abs(int a);

int main(void)
{
    int k=0,count=0;
    long int ans=0,i=1;
    scanf("%d",&k);

    while(true){
        if(loop(i)==true){
            ans=i;
            count+=1;
            if(count==k) break;
        }
        i++;
    }
    printf("%ld",ans);
}

int loop(long int a){
    int right=0,left=0;
    int flag=true;
    while(true){
        if(a-10<0) break;
        right=a%10;
        left=(a/10)%10;
        if(abs(right-left)<=1){
            a=a/10;
            loop(a);
        } else {
            flag=false;
            break;
        }
    }
    return flag;
}

int abs(int a){
    if(a<0) a=(-1)*a;
    return a;
}


#include <stdio.h>
#define true 1
#define false 0

int loop(int a);
int abs(int a);

int main(void)
{
    int k=0,ans=0,count=0;
    scanf("%d",&k);

    for(int i=1;i<100000;i++){
        if(loop(i)==true){
            ans=i;
            count+=1;
            if(count==k) break;
        }
    }
    printf("%d",ans);
}

int loop(int a){
    int right=0,left=0;
    int flag=true;
    while(true){
        if(a-10<0) break;
        right=a%10;
        left=(a/10)%10;
        if(abs(right-left)<=1){
            a=a/10;
            loop(a);
        } else {
            flag=false;
            break;
        }
    }
    return flag;
}

int abs(int a){
    if(a<0) a=(-1)*a;
    return a;
}


#include <stdio.h>
#define true 1
#define false 0

int loop(int a);
int abs(int a);

int main(void)
{
    int k=0,ans=0,count=0;
    scanf("%d",&k);

    for(int i=1;i<100000;i++){
        if(loop(i)==true){
            ans=i;
            count+=1;
            if(count==k) break;
        }
    }
    printf("%d",ans);
}

int loop(int a){
    int right=0,left=0;
    int flag=true;
    while(true){
        if(a-10<0) break;
        right=a%10;
        left=(a/10)%10;
        if(abs(right-left)<=1){
            a=a/100;
            loop(a);
        } else {
            flag=false;
            break;
        }
    }
    return flag;
}

int abs(int a){
    if(a<0) a=(-1)*a;
    return a;
}


/*!
 * path: atcoder/abc161/d
 * URL: https://github.com/koukimetal/procomvis/tree/master/src/contest/atcoder/abc161/d
 */!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};t.__esModule=!0;var o=r(n(1)),u=n(2);o.default.readFile("/dev/stdin","utf8",(function(e,t){!function(e){var t=new u.Solver,n=t.parse(e),r=t.solve(n);t.print(r)}(t)}))},function(e,t){e.exports=require("fs")},function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});t.__esModule=!0;var u=n(3),i=n(4);function a(e,t){if(e.num.length===t){var n=new Array(e.num.length+1);n.fill(0),n[n.length-1]=1,e.num=n}else e.num.length-1===t?9===e.num[t]?a(e,t+1):e.num[t]++:e.num[t]<9&&Math.abs(e.num[t]+1-e.num[t+1])<=1?e.num[t]++:(a(e,t+1),e.num[t]=Math.max(0,e.num[t+1]-1))}var l=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.solve=function(e){for(var t=e.K,n={num:[]},r=0;r<t;r++)a(n,0);return{answer:n.num}},t.prototype.parse=function(e){return{K:i.getSpaceIterator(e,(function(e){return parseInt(e)})).next().value}},t.prototype.print=function(e){var t=e.answer.reverse().join("");console.log(t)},t}(u.SolverBase);t.Solver=l},function(e,t,n){"use strict";t.__esModule=!0;var r=function(){};t.SolverBase=r},function(e,t,n){"use strict";var r=this&&this.__generator||function(e,t){var n,r,o,u,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return u={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(u[Symbol.iterator]=function(){return this}),u;function a(u){return function(a){return function(u){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&u[0]?r.return:u[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,u[1])).done)return o;switch(r=0,o&&(u=[2&u[0],o.value]),u[0]){case 0:case 1:o=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,r=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===u[0]||2===u[0])){i=0;continue}if(3===u[0]&&(!o||u[1]>o[0]&&u[1]<o[3])){i.label=u[1];break}if(6===u[0]&&i.label<o[1]){i.label=o[1],o=u;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(u);break}o[2]&&i.ops.pop(),i.trys.pop();continue}u=t.call(e,i)}catch(e){u=[6,e],r=0}finally{n=o=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,a])}}};t.__esModule=!0,t.getSpaceIterator=function(e,t){var n,o;return r(this,(function(r){switch(r.label){case 0:n=0,o=e.split(/\s+/).map((function(e){return t(e)})),r.label=1;case 1:return n<o.length?[4,o[n]]:[3,4];case 2:r.sent(),r.label=3;case 3:return n++,[3,1];case 4:return[2,void 0]}}))}}]);


var obj = init();
Main();
function nextInt(){return myconv(next(),1);}
function nextStrArray(){return myconv(next(),2);}//半角スペース分割
function nextIntArray(){return myconv(next(),4);}//半角スペース + 数値化
function nextCharArray(){return myconv(next(),6);}//1文字分割
function next(){return obj.next();}
function hasNext(){return obj.hasNext();}
function myin(){return require("fs").readFileSync("/dev/stdin", "utf8").trim().split("\n");}
function init(){
  var inputFile = myin();
  var returnObj = {
    "list" : inputFile, "index" : 0, "max" : inputFile.length,
    "hasNext" : function(){return (this.index < this.max);},
    "next" : function(){if(!this.hasNext()){throw "ArrayIndexOutOfBoundsException これ以上ないよ";}else{var returnInput = this.list[this.index];this.index++;return returnInput;}}
  };
  return returnObj;
}
function myout(t){console.log(t);}//標準出力
function myerr(t){console.error(t);}//標準エラー出力
//[no]要素の扱い。数値型
//不明値、異常時:引数そのまま返す　1:数値へ変換
//2:半角SPで分割 4:半角SPで分割し、数値配列へ
//6:1文字で分割  7:1文字で分割し、数値配列へ
//8:半角SPで結合 9:改行で結合 0:文字なしで結合
function myconv(i,no){try{switch(no){case 1:return parseInt(i);case 2:return i.split(" ");case 4:return i.split(" ").map((a)=>Number(a));case 6:return i.split("");case 7:return i.split("").map((a)=>Number(a));case 8:return i.join(" ");case 9:return i.join("\n");case 0:return i.join("");default:return i;}}catch(e){return i;}}
function Main(){
  var K = nextInt();
  var queue = [1,2,3,4,5,6,7,8,9];
  var last = 0;
  for(var i = 0; i < K; i++){
    var tmp = queue[i];
    last = tmp;
    switch(last % 10){
      case 0:
        queue.push(last * 10);
        queue.push(last * 10 + 1);
        break;
      case 9:
        queue.push(last * 10 + 8);
        queue.push(last * 10 + 9);
        break;
      default:
        queue.push(last * 10 + last % 10 - 1);
        queue.push(last * 10 + last % 10);
        queue.push(last * 10 + last % 10 + 1);
        break;
                    }

  }
  //myerr(queue);
  myout(queue[K - 1]);
}


function main(input) {
  const inputs = input.split('\n')
  const [K] = inputs[0].split(' ').map(Number)
  // console.log(K)
  const a = [1,2,3,4,5,6,7,8,9]
  let p = 0
  while(true) {
    // console.log(K, p, a.length, a)
    if (K <= a.length) {
      // console.log('OK:', K, a.length)
      console.log(a[K - 1])
      return
    }
    const len = a.length
    for(let i = p; i < len; i++) {
      for (let j = -1; j <= 1; j++) {
        let k = String(a[i])
        let d = a[i] % 10 + j
        if (d < 10 && 0 <= d) {
          const nn = k + String((a[i] % 10) + j)
          a.push(Number(nn))
        }
      }
      p++
    }
  }
  // console.log(a)
  // console.log('finished')
}
main(require("fs").readFileSync("/dev/stdin", "utf8"));


"use strict";

const gen = function (first, digit) {
    if(first == 1 && digit == 1) return [1,2,3,4,5,6,7,8,9]
    let q = [[first]]
    let ans = []
    while (q.length > 0) {
        let tmp = q.shift()
        if (tmp.length == digit) {
            ans.push(Number(tmp.join("")))
            continue
        }
        const last = tmp[tmp.length - 1]
        if (last !== 0) q.push([...tmp, last - 1])
        q.push([...tmp, last])
        if (last !== 9) q.push([...tmp, last + 1])
    }
    return ans
}

const main = arg => {
    const input = arg.trim().split("\n");

    let K = parseInt(input[0].split(" ")[0]);
    let first = 1
    let digit = 1
    while(K > 0){
        let tmp = gen(first, digit)
        // console.log(K, first, digit, tmp)
        if(tmp.length >= K){
            console.log(tmp[K-1])
            return
        }
        K = K - tmp.length
        if(first==1 && digit == 1){
            digit++
        }else if(first !== 9){
            first++
        }else{
            first = 1
            digit++
        }
    }
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


    function Main(input){
        k=parseInt(input);
        i=12;
        c=12;
        while(c<k){
            i++;
            a=parseInt(String(i).substr(0,1));
            b=parseInt(String(i).substr(1,1));
            if(a-b<-1){
                i=(parseInt(String(i).substr(0,1))+1)*(10**(String(i).length-1));
            }
            a=parseInt(String(i).substr(0,1));
            b=parseInt(String(i).substr(1,1));
            if(a-b>1){
                tmp=parseInt(String(i).substr(0,1))*(10**(String(i).length-1));
                tmp2=(parseInt(String(tmp).substr(0,1))-1)*(10**(String(i).length-2));
                tmp3=parseInt(String(i-tmp).substr(0,1))*(10**(String(i).length-2));
                i=tmp+tmp2+(i-tmp-tmp3);
            }
            p=true;
            for(ii=0;ii<String(i).length-1;ii++){
                a=parseInt(String(i).substr(ii,1));
                b=parseInt(String(i).substr(ii+1,1));
                if(Math.abs(a-b)>1){
                    p=false;
                    break;
                }
            }
            if(p==true){
                c++;
            }
        }
        if(k>=10){
            console.log(String(i));
        }else{
            console.log(String(k));
        }
    }
    Main(require("fs").readFileSync("/dev/stdin", "utf8"));


    function Main(input){
        k=parseInt(input);
        i=12;
        c=12;
        while(c<k){
            i++;
            a=parseInt(String(i).substr(0,1));
            b=parseInt(String(i).substr(1,1));
            if(a-b<-1){
                i=(parseInt(String(i).substr(0,1))+1)*(10**(String(i).length-1));
            }
            a=parseInt(String(i).substr(0,1));
            b=parseInt(String(i).substr(1,1));
            if(a-b>1){
                tmp=parseInt(String(i).substr(0,1))*(10**(String(i).length-1));
                tmp2=(parseInt(String(tmp).substr(0,1))-1)*(10**(String(i).length-2));
                tmp3=parseInt(String(i-tmp).substr(0,1))*(10**(String(i).length-2));
                i=tmp+tmp2+(i-tmp-tmp3);
            }
            p=true;
            for(ii=0;ii<String(i).length-1;ii++){
                a=parseInt(String(i).substr(ii,1));
                b=parseInt(String(i).substr(ii+1,1));
                if(Math.abs(a-b)>1){
                    p=false;
                    break;
                }
            }
            if(p==true){
                c++;
            }
        }
        if(k>=10){
            console.log(i);
        }else{
            console.log(k);
        }
    }
    Main(require("fs").readFileSync("/dev/stdin", "utf8"));


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)
	dpTable0 := make([]int, 12)
	dpTable[0] = dpTable0
	for i := 1; i <= 10; i++ {
		dpTable0[i] = 1
	}

	lunlunCount := 9
	rowI := 0
	colI := 1
	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 {
				lunlunCount += dpRowI
				if lunlunCount >= k {
					break
				}
			}
		}
	}
	restLunlunCount := k - (lunlunCount - dpTable[rowI][colI])

	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

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
}

// * 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
}


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
	//     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
}