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.42.0) (judge verdict: Accepted)

use crate::automaton_dp::{Dfa, Monoid};
use proconio::{input, marker::Bytes};

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

    let ans = automaton_dp::automaton_dp(
        AlmostEverywhereZero {
            n: n.iter().map(|c| (c - b'0').into()).collect(),
            k,
        },
        0..=9,
        n.len(),
        |&x, _| x,
        1,
    );

    println!("{}", ans);
}

impl Monoid for u64 {
    fn op(&self, rhs: &Self) -> Self {
        self + rhs
    }

    fn identity() -> Self {
        0
    }
}

struct AlmostEverywhereZero {
    n: Vec<u64>,
    k: usize,
}

#[derive(PartialEq, Eq, Hash, Debug)]
struct State {
    i: usize,
    num_non_zeros: usize,
    surely_less_than_n: bool,
}

impl Dfa for AlmostEverywhereZero {
    type Char = u64;
    type State = State;

    fn initial_state(&self) -> Option<Self::State> {
        Some({
            State {
                i: 0,
                num_non_zeros: 0,
                surely_less_than_n: false,
            }
        })
    }

    fn next_state(&self, state: &Self::State, &c: &u64) -> Option<State> {
        let Self { n, k } = self;
        let State {
            i,
            num_non_zeros,
            surely_less_than_n,
        } = state;

        if *surely_less_than_n {
            if num_non_zeros + usize::from(c > 0) <= *k {
                Some(State {
                    i: i + 1,
                    num_non_zeros: num_non_zeros + usize::from(c > 0),
                    surely_less_than_n: true,
                })
            } else {
                None
            }
        } else if c <= n[*i] && num_non_zeros + usize::from(c > 0) <= *k {
            Some(State {
                i: i + 1,
                num_non_zeros: num_non_zeros + usize::from(c > 0),
                surely_less_than_n: c < n[*i],
            })
        } else {
            None
        }
    }

    fn is_accept_state(&self, state: &Self::State) -> bool {
        state.num_non_zeros == self.k
    }
}

// fn solve(k: usize, len: usize, digit: impl Fn(usize) -> u64) -> u64 {
//     let mut dp = vec![vec![[0; 2]; k + 1]; len];
//
//     dp[0][0][1] = 1;
//     dp[0][1][0] = 1;
//     dp[0][1][1] = digit(0) - 1;
//
//     for i in 1..len {
//         dp[i][0][1] = 1;
//         for j in 1..=k {
//             dp[i][j][0] = dp[i - 1][j - usize::from(digit(i) > 0)][0];
//             dp[i][j][1] = u64::from(digit(i) > 0) * dp[i - 1][j][0]
//                 + digit(i).saturating_sub(1) * dp[i - 1][j - 1][0]
//                 + dp[i - 1][j][1]
//                 + 9 * dp[i - 1][j - 1][1];
//         }
//     }
//
//     dp[len - 1][k][0] + dp[len - 1][k][1]
// }

pub mod automaton_dp {
    use std::collections::HashMap;
    use std::hash::Hash;
    use std::mem;

    pub trait Monoid {
        fn op(&self, rhs: &Self) -> Self;
        fn identity() -> Self;
    }

    pub trait Dfa {
        type Char;
        type State;

        fn initial_state(&self) -> Option<Self::State>;
        fn next_state(&self, state: &Self::State, c: &Self::Char) -> Option<Self::State>;
        fn is_accept_state(&self, state: &Self::State) -> bool;
    }

    pub fn automaton_dp<A, M>(
        dfa: A,
        sigma: impl Iterator<Item = A::Char> + Clone,
        len: usize,
        mut mul: impl FnMut(&M, &A::Char) -> M,
        e: M,
    ) -> M
    where
        A: Dfa,
        A::State: Eq + Hash + std::fmt::Debug,
        M: Monoid + std::fmt::Debug,
    {
        let mut dp = HashMap::<A::State, M>::new();
        let mut dp_next = HashMap::<A::State, M>::new();

        if let Some(initial_state) = dfa.initial_state() {
            dp.insert(initial_state, e);
        }
        for _ in 0..len {
            for (state, value) in dp.drain() {
                for c in sigma.clone() {
                    if let Some(next_state) = dfa.next_state(&state, &c) {
                        let value = mul(&value, &c);
                        dp_next
                            .entry(next_state)
                            .and_modify(|acc| *acc = acc.op(&value))
                            .or_insert(value);
                    }
                }
            }
            mem::swap(&mut dp, &mut dp_next);
            dp_next.clear();
        }

        let mut acc = M::identity();
        for (state, value) in dp {
            if dfa.is_accept_state(&state) {
                acc = acc.op(&value);
            }
        }
        acc
    }
}

pub mod nfa_dp {
    use std::collections::HashMap;
    use std::hash::Hash;
    use std::mem;

    pub trait Monoid {
        fn op(&self, rhs: &Self) -> Self;
        fn identity() -> Self;
    }

    pub trait Nfa {
        type Char;
        type State;

        fn initial_state(&self) -> Option<Self::State>;
        fn next_states(&self, state: &Self::State, c: &Self::Char) -> Vec<Self::State>;
        fn is_accept_state(&self, state: &Self::State) -> bool;
    }

    pub fn automaton_dp<A, M>(
        nfa: A,
        sigma: impl Iterator<Item = A::Char> + Clone,
        len: usize,
        mut mul: impl FnMut(&M, &A::Char) -> M,
        e: M,
    ) -> M
    where
        A: Nfa,
        A::State: Eq + Hash + std::fmt::Debug,
        M: Monoid + std::fmt::Debug,
    {
        let mut dp = HashMap::<A::State, M>::new();
        let mut dp_next = HashMap::<A::State, M>::new();

        if let Some(initial_state) = nfa.initial_state() {
            dp.insert(initial_state, e);
        }
        for _ in 0..len {
            for (state, value) in dp.drain() {
                for c in sigma.clone() {
                    for next_state in nfa.next_states(&state, &c) {
                        let value = mul(&value, &c);
                        dp_next
                            .entry(next_state)
                            .and_modify(|acc| *acc = acc.op(&value))
                            .or_insert(value);
                    }
                }
            }
            mem::swap(&mut dp, &mut dp_next);
            dp_next.clear();
        }

        let mut acc = M::identity();
        for (state, value) in dp {
            if nfa.is_accept_state(&state) {
                acc = acc.op(&value);
            }
        }
        acc
    }
}