#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}

macro_rules! trace {
    ($x:expr) => { dbg!($x); };
    ($($xs:expr),*) => { dbg!(($($xs),*)); }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

const M: i64 = 1_000_000_007;

// n^m
struct PowerPermutation { n: usize, m: usize, ar: Vec<usize> }
impl PowerPermutation {
    fn new(n: usize, m: usize) -> PowerPermutation {
        let ar = vec![0; m];
        PowerPermutation { n: n, m: m, ar: ar }
    }
}
impl Iterator for PowerPermutation {
    type Item = Vec<usize>;
    fn next(&mut self) -> Option<Vec<usize>> {
        if self.ar[self.m-1] >= self.n { return None }
        let r = self.ar.clone();
        self.ar[0] += 1;
        for i in 0..self.m-1 {
            if self.ar[i] == self.n {
                self.ar[i] = 0;
                self.ar[i + 1] += 1;
            } else {
                break;
            }
        }
        return Some(r);
    }
}

fn leq(x: &Vec<u8>, y: &Vec<u8>) -> bool {
    if x.len() < y.len() { return true }
    if x.len() > y.len() { return false }
    for i in 0..x.len() {
        if x[i] < y[i] { return true }
        if x[i] > y[i] { return false }
    }
    true
}

fn main() {
    let mut sc = Scanner::new();
    let n: String = sc.cin();
    let n: Vec<u64> = n.chars().map(|c|
        ((c as u8) - ('0' as u8)) as u64
    ).collect();
    let k: usize = sc.cin();

    let mut dp = vec![vec![vec![0; 4]; 2]; n.len()];

    dp[0][0][0] = 1;
    dp[0][0][1] = n[0] - 1;
    dp[0][1][1] = 1;
    for i in 1..n.len() {
        for k in 0..4 {
            dp[i][0][k] += dp[i-1][0][k];
            if n[i] > 0 {
                dp[i][0][k] += dp[i-1][1][k];
            }
            if k > 0 {
                dp[i][0][k] += dp[i-1][0][k-1] * 9;
            }
            if k > 0 && n[i] > 0 {
                dp[i][0][k] += dp[i-1][1][k-1] * (n[i] - 1);
            }

            if n[i] == 0 {
                dp[i][1][k] = dp[i-1][1][k];
            }
            if n[i] > 0 && k > 0 {
                dp[i][1][k] = dp[i-1][1][k-1];
            }
        }
        // trace!(i, &dp[i]);
    }

    put!(dp[n.len()-1][0][k] + dp[n.len()-1][1][k]);

}

use std::io::{self, Write};
use std::str::FromStr;
use std::collections::VecDeque;

struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
impl Scanner {
    fn new() -> Self { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> { self.cin::<String>().chars().collect() }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> { (0..n).map(|_| self.cin()).collect() }
}


Measured memory_bytes: 4352