use std::{cmp::Ordering, collections::HashMap, hash::Hash}; use proconio::{input, marker::Bytes}; fn main() { input! { a: Bytes, b: Bytes, } let dfa = And(Or(MultipleOf(3), Seen(b'3')), Not(MultipleOf(8))); let hi = count(And(dfa.clone(), Le(&b)), b'0'..=b'9', b.len()); let lo = count(And(dfa.clone(), Lt(&a)), b'0'..=b'9', a.len()); println!("{}", (hi + MOD - lo) % MOD); } const MOD: u64 = 1_000_000_007; fn count(dfa: A, sigma: impl Iterator + Clone, len: usize) -> u64 where A: Dfa, A::State: Eq + Hash, { let mut dp = HashMap::new(); dp.insert(dfa.init(), 1); for _ in 0..len { let mut ndp = HashMap::new(); for (q, v) in dp { for c in sigma.clone() { let e = ndp.entry(dfa.next(&q, &c)).or_insert(0); *e = (*e + v) % MOD; } } dp = ndp; } dp.iter() .filter_map(|(q, v)| dfa.accept(q).then_some(v)) .fold(0, |sum, v| (sum + v) % MOD) } trait Dfa { type State; type Alphabet; fn init(&self) -> Self::State; fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State; fn accept(&self, q: &Self::State) -> bool; } #[derive(Clone)] struct And(A, B); impl> Dfa for And { type State = (A::State, B::State); type Alphabet = A::Alphabet; fn init(&self) -> Self::State { (self.0.init(), self.1.init()) } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { (self.0.next(&q.0, c), self.1.next(&q.1, c)) } fn accept(&self, q: &Self::State) -> bool { self.0.accept(&q.0) && self.1.accept(&q.1) } } #[derive(Clone)] struct Or(A, B); impl> Dfa for Or { type State = (A::State, B::State); type Alphabet = A::Alphabet; fn init(&self) -> Self::State { (self.0.init(), self.1.init()) } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { (self.0.next(&q.0, c), self.1.next(&q.1, c)) } fn accept(&self, q: &Self::State) -> bool { self.0.accept(&q.0) || self.1.accept(&q.1) } } #[derive(Clone)] struct Not(A); impl Dfa for Not { type State = A::State; type Alphabet = A::Alphabet; fn init(&self) -> Self::State { self.0.init() } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { self.0.next(q, c) } fn accept(&self, q: &Self::State) -> bool { !self.0.accept(q) } } #[derive(Clone)] struct MultipleOf(u64); impl Dfa for MultipleOf { type State = u64; type Alphabet = u8; fn init(&self) -> Self::State { 0 } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { (q * 10 + (c - b'0') as u64) % self.0 } fn accept(&self, q: &Self::State) -> bool { *q == 0 } } #[derive(Clone)] struct Seen(u8); impl Dfa for Seen { type State = bool; type Alphabet = u8; fn init(&self) -> Self::State { false } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { *q || *c == self.0 } fn accept(&self, q: &Self::State) -> bool { *q } } #[derive(Clone)] struct Lt<'a>(&'a [u8]); impl Dfa for Lt<'_> { type State = (Ordering, usize); type Alphabet = u8; fn init(&self) -> Self::State { (Ordering::Equal, 0) } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { (q.0.then(c.cmp(&self.0[q.1])), q.1 + 1) } fn accept(&self, q: &Self::State) -> bool { q.0.is_lt() } } #[derive(Clone)] struct Le<'a>(&'a [u8]); impl Dfa for Le<'_> { type State = (Ordering, usize); type Alphabet = u8; fn init(&self) -> Self::State { (Ordering::Equal, 0) } fn next(&self, q: &Self::State, c: &Self::Alphabet) -> Self::State { (q.0.then(c.cmp(&self.0[q.1])), q.1 + 1) } fn accept(&self, q: &Self::State) -> bool { q.0.is_le() } }