Problem:
Score : 500 points

Problem Statement

Find the number of integers between 1 and N (inclusive) that contains exactly K non-zero digits when written in base ten.

Constraints

1 \leq N < 10^{100}

1 \leq K \leq 3

Input

Input is given from Standard Input in the following format:

N
K

Output

Print the count.

Sample Input 1

100
1

Sample Output 1

19

The following 19 integers satisfy the condition:

1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100

Sample Input 2

25
2

Sample Output 2

14

The following 14 integers satisfy the condition:

11,12,13,14,15,16,17,18,19,21,22,23,24,25

Sample Input 3

314159
2

Sample Output 3

937

Sample Input 4

9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
3

Sample Output 4

117879300

Solution in Rust (1.15.1) (judge verdict: Accepted)

#![allow(unused_macros, deprecated)]

#[allow(dead_code)]
mod utils {
    use std::collections::{HashMap, HashSet};
    use std::hash::{BuildHasherDefault, Hash, Hasher};
    use std::io::{
        self, BufRead, BufReader, BufWriter, Seek, SeekFrom, Stdin, StdinLock, Stdout, StdoutLock,
        Write,
    };
    use std::mem;
    use std::ops::{Deref, DerefMut};
    use std::ptr;
    use std::slice;
    use std::str::{self, FromStr};

    #[inline]
    fn is_space_or_line_break(b: &u8) -> bool {
        *b == b' ' || *b == b'\n'
    }

    pub struct Scanner<R: BufRead> {
        reader: R,
        buf: Vec<u8>,
    }

    impl<R: BufRead> Scanner<R> {
        #[inline]
        pub fn new(reader: R) -> Scanner<R> {
            Scanner {
                reader: reader,
                buf: Vec::with_capacity(100),
            }
        }

        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_until(is_space_or_line_break);
            self.parse()
        }

        pub fn read2<T1: FromStr, T2: FromStr>(&mut self) -> (T1, T2) {
            (self.read(), self.read())
        }

        pub fn read3<T1: FromStr, T2: FromStr, T3: FromStr>(&mut self) -> (T1, T2, T3) {
            (self.read(), self.read(), self.read())
        }

        pub fn read4<T1: FromStr, T2: FromStr, T3: FromStr, T4: FromStr>(
            &mut self,
        ) -> (T1, T2, T3, T4) {
            (self.read(), self.read(), self.read(), self.read())
        }

        pub fn reads(&mut self) -> &str {
            self.read_until(is_space_or_line_break);
            unsafe { str::from_utf8_unchecked(&self.buf) }
        }

        pub fn readl(&mut self) -> &str {
            self.buf.clear();
            self.reader.read_until(b'\n', &mut self.buf).unwrap();
            let bytes = if self.buf.last() == Some(&b'\n') {
                &self.buf[..self.buf.len() - 1]
            } else {
                &self.buf
            };
            unsafe { str::from_utf8_unchecked(&bytes) }
        }

        pub fn read_vec<T: FromStr>(&mut self, count: usize) -> Vec<T> {
            (0..count).map(|_| self.read()).collect()
        }

        fn read_until<P: FnMut(&u8) -> bool>(&mut self, mut predicate: P) {
            self.buf.clear();
            let mut first = true;

            // https://doc.rust-lang.org/src/std/io/mod.rs.html#1623-1649
            loop {
                let (done, used) = {
                    let available = self.reader.fill_buf().unwrap();
                    if first && available.len() == 0 {
                        panic!("Scan Error (EOF reached)");
                    }

                    match available.iter().position(&mut predicate) {
                        Some(0) if first => (false, 1),
                        Some(i) => {
                            self.buf.extend_from_slice(&available[..i]);
                            (true, i + 1)
                        }
                        None => {
                            self.buf.extend_from_slice(available);
                            (false, available.len())
                        }
                    }
                };

                self.reader.consume(used);
                if done || used == 0 {
                    return;
                }

                first = false;
            }
        }

        #[inline]
        fn parse<T: FromStr>(&mut self) -> T {
            // 文字列をT型へパースする
            let elem = unsafe { str::from_utf8_unchecked(&self.buf) };
            elem.parse()
                .unwrap_or_else(|_| panic!(format!("failed parsing: {}", elem)))
        }
    }

    impl<R: BufRead + Seek> Seek for Scanner<R> {
        #[inline]
        fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
            self.reader.seek(pos)
        }
    }

    pub struct StdinScanner {
        stdin: Stdin,
        scanner: Scanner<BufReader<StdinLock<'static>>>,
    }

    impl StdinScanner {
        #[inline]
        pub fn new() -> StdinScanner {
            let stdin = io::stdin();
            let stdinlock = unsafe { mem::transmute(stdin.lock()) };
            let reader = BufReader::with_capacity(4096, stdinlock);
            let scanner = Scanner::new(reader);
            StdinScanner {
                stdin: stdin,
                scanner: scanner,
            }
        }
    }

    impl Deref for StdinScanner {
        type Target = Scanner<BufReader<StdinLock<'static>>>;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.scanner
        }
    }

    impl DerefMut for StdinScanner {
        #[inline]
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.scanner
        }
    }

    pub struct StdoutWriter {
        stdout: Stdout,
        writer: BufWriter<StdoutLock<'static>>,
    }

    impl StdoutWriter {
        #[inline]
        pub fn new() -> StdoutWriter {
            let stdout = io::stdout();
            let stdoutlock = unsafe { mem::transmute(stdout.lock()) };
            let writer = BufWriter::with_capacity(4096, stdoutlock);
            StdoutWriter {
                stdout: stdout,
                writer: writer,
            }
        }

        pub fn write<T: Writable>(&mut self, v: T) {
            v.display(&mut self.writer);
        }

        pub fn writeln<T: Writable>(&mut self, v: T) {
            v.display(&mut self.writer);
            self.writer.write_all(b"\n").unwrap();
        }

        pub fn write_horizontal<I>(&mut self, iter: I)
        where
            I: IntoIterator,
            I::Item: Writable,
        {
            let mut it = iter.into_iter();
            if let Some(elem) = it.next() {
                elem.display(&mut self.writer);
            } else {
                return;
            }

            for elem in it {
                elem.display(&mut self.writer);
                self.writer.write_all(b" ").unwrap();
            }
        }

        pub fn write_vertical<I>(&mut self, iter: I)
        where
            I: IntoIterator,
            I::Item: Writable,
        {
            let mut it = iter.into_iter();
            if let Some(elem) = it.next() {
                elem.display(&mut self.writer);
            } else {
                return;
            }

            for elem in it {
                elem.display(&mut self.writer);
                self.writer.write_all(b"\n").unwrap();
            }
        }
    }

    impl Write for StdoutWriter {
        #[inline]
        fn flush(&mut self) -> io::Result<()> {
            self.writer.flush()
        }

        #[inline]
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.writer.write(buf)
        }
    }

    #[derive(Clone)]
    pub struct FNVHasher(u64);

    impl Default for FNVHasher {
        fn default() -> FNVHasher {
            FNVHasher(0xcbf29ce484222325)
        }
    }

    impl Hasher for FNVHasher {
        #[inline]
        fn write(&mut self, bytes: &[u8]) {
            let FNVHasher(mut hash) = *self;

            for byte in bytes.iter() {
                hash = hash ^ (*byte as u64);
                hash = hash.wrapping_mul(0x100000001b3);
            }

            *self = FNVHasher(hash);
        }

        #[inline]
        fn finish(&self) -> u64 {
            self.0
        }
    }

    pub type FNVSet<T> = HashSet<T, BuildHasherDefault<FNVHasher>>;
    pub type FNVMap<K, V> = HashMap<K, V, BuildHasherDefault<FNVHasher>>;

    #[inline]
    pub fn fnvset_new<T: Eq + Hash>() -> FNVSet<T> {
        FNVSet::<T>::with_hasher(BuildHasherDefault::default())
    }

    #[inline]
    pub fn fnvset_with_capacity<T: Eq + Hash>(n: usize) -> FNVSet<T> {
        FNVSet::<T>::with_capacity_and_hasher(n, BuildHasherDefault::default())
    }

    #[inline]
    pub fn fnvmap_new<K: Eq + Hash, V>() -> FNVMap<K, V> {
        FNVMap::<K, V>::with_hasher(BuildHasherDefault::default())
    }

    #[inline]
    pub fn fnvmap_with_capacity<K: Eq + Hash, V>(n: usize) -> FNVMap<K, V> {
        FNVMap::<K, V>::with_capacity_and_hasher(n, BuildHasherDefault::default())
    }

    static DEC_DIGITS_LUT: &'static [u8; 200] = b"0001020304050607080910111213141516171819\
            2021222324252627282930313233343536373839\
            4041424344454647484950515253545556575859\
            6061626364656667686970717273747576777879\
            8081828384858687888990919293949596979899";

    fn write_int<W: Write>(mut writer: W, mut n: u64, is_negative: bool) {
        unsafe {
            let mut buf: [u8; 39] = mem::uninitialized();
            let buf_ptr_start = buf.as_mut_ptr().offset(39);
            let mut buf_ptr = buf_ptr_start;
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            while n >= 10000 {
                let rem = (n % 10000) as isize;
                n /= 10000;

                let d1 = (rem / 100) << 1;
                let d2 = (rem % 100) << 1;
                buf_ptr = buf_ptr.offset(-4);
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr, 2);
                ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(2), 2);
            }

            let mut n = n as isize; // possibly reduce 64bit math

            // decode 2 more chars, if > 2 chars
            if n >= 100 {
                let d1 = (n % 100) << 1;
                n /= 100;
                buf_ptr = buf_ptr.offset(-2);
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr, 2);
            }

            // decode last 1 or 2 chars
            if n < 10 {
                buf_ptr = buf_ptr.offset(-1);
                *buf_ptr = (n as u8) + b'0';
            } else {
                let d1 = n << 1;
                buf_ptr = buf_ptr.offset(-2);
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr, 2);
            }

            if is_negative {
                buf_ptr = buf_ptr.offset(-1);
                *buf_ptr = b'-';
            }

            let buf_slice =
                slice::from_raw_parts(buf_ptr, buf_ptr_start as usize - buf_ptr as usize);

            writer.write_all(buf_slice).unwrap();
        }
    }

    pub trait Writable {
        fn display<W: Write>(&self, writer: &mut W);
    }

    impl Writable for str {
        #[inline]
        fn display<W: Write>(&self, writer: &mut W) {
            writer.write_all(self.as_bytes()).unwrap()
        }
    }

    impl<'a> Writable for &'a str {
        #[inline]
        fn display<W: Write>(&self, writer: &mut W) {
            writer.write_all(self.as_bytes()).unwrap()
        }
    }

    impl Writable for String {
        #[inline]
        fn display<W: Write>(&self, writer: &mut W) {
            writer.write_all(self.as_bytes()).unwrap()
        }
    }

    impl Writable for bool {
        #[inline]
        fn display<W: Write>(&self, writer: &mut W) {
            let s: &'static [u8] = if *self { b"Yes" } else { b"No" };
            writer.write_all(s).unwrap();
        }
    }

    macro_rules! impl_writable_int {
        ($($int:ty)*) => {
            $(
                impl Writable for $int {
                    #[allow(unused_comparisons)]
                    fn display<W: Write>(&self, writer: &mut W) {
                        let is_negative = !(*self >= 0);
                        let abs = if is_negative {
                            (!*self as u64).wrapping_add(1)
                        } else {
                            *self as u64
                        };
                        write_int(writer, abs, is_negative);
                    }
                }
            )*
        };
    }

    macro_rules! impl_writable_float {
        ($($float:ty)*) => {
            $(
                impl Writable for $float {
                    #[inline]
                    fn display<W: Write>(&self, writer: &mut W) {
                        write!(writer, "{}", *self).unwrap();
                    }
                }
            )*
        }
    }

    impl_writable_int!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize);
    impl_writable_float!(f32 f64);
}

fn solve(n: &[u8], k: usize) -> usize {
    if k == 1 {
        return (n[0] - b'0') as usize + 9 * (n.len() - 1);
    };

    let mut result = if k == 2 {
        9 * (n.len() - 1)
    } else {
        81 * (n.len() - 1) * (n.len() - 2) / 2
    };

    result *= (n[0] - b'0') as usize - 1;

    if n.len() > k {
        result += if k == 2 {
            81 * (n.len() - 1) * (n.len() - 2) / 2
        } else {
            729 * (n.len() - 1) * (n.len() - 2) * (n.len() - 3) / 6
        }
    }

    let next_nonzero = n[1..].iter().position(|&b| b != b'0');
    if let Some(p) = next_nonzero {
        result += solve(&n[p + 1..], k - 1);
    }

    return result;
}

fn main() {
    let mut scanner = utils::StdinScanner::new();
    let mut writer = utils::StdoutWriter::new();

    let n = scanner.read::<String>();
    let k = scanner.read::<usize>();

    if n.len() < k {
        writer.writeln(0);
        return;
    }

    writer.writeln(solve(n.as_bytes(), k));
}