diff --git a/src/problem/mod.rs b/src/problem/mod.rs index a6aec31..9cae9b8 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -240,4 +240,5 @@ mod p2848_points_that_intersect_with_cars; mod p1184_distance_between_bus_stops; mod p815_bus_routes; mod p2332_the_latest_time_to_catch_a_bus; -mod p2414_length_of_the_longest_alphabetical_continuous_substring; \ No newline at end of file +mod p2414_length_of_the_longest_alphabetical_continuous_substring; +mod p2376_count_special_integers; \ No newline at end of file diff --git a/src/problem/p2376_count_special_integers.rs b/src/problem/p2376_count_special_integers.rs new file mode 100644 index 0000000..ac37f09 --- /dev/null +++ b/src/problem/p2376_count_special_integers.rs @@ -0,0 +1,86 @@ + +/** + * [2376] Count Special Integers + */ +pub struct Solution {} + + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn count_special_numbers(n: i32) -> i32 { + + let n: Vec = n.to_string().chars().map(|c| c.to_digit(10).unwrap() as i32).collect(); + + let mut result = 0; + let mut candidate = 9; + + // 计算位数小于n的特殊整数 + for i in 0..n.len() as i32 - 1 { + result += candidate; + candidate *= 9 - i + } + + let mut memory: HashMap = HashMap::new(); + + result += Self::dp(0, false, &mut memory, &n); + + result + } + + // mask 表示前缀中使用过的数字 使用二进制表示 + // prefix_smaller 当前的前缀是否小于n的前缀 + fn dp(mask: i32, prefix_smaller: bool, memory: &mut HashMap, number: &Vec) -> i32 { + let used_bits = mask.count_ones() as usize; + if used_bits == number.len() { + return 1; + } + + let key = mask * 2 + if prefix_smaller { + 1 + } else { + 0 + }; + + if !memory.contains_key(&key) { + let mut result = 0; + + let lower_bound = if mask == 0 { + 1 + } else { + 0 + }; + + let upper_bound = if prefix_smaller { + 9 + } else { + number[used_bits] + }; + + for i in lower_bound..=upper_bound { + if mask >> i & 1 == 0 { + result += Self::dp(mask | 1 << i, prefix_smaller || i < upper_bound, memory, number); + } + } + + memory.insert(key, result); + } + + *memory.get(&key).unwrap() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2376() { + assert_eq!(19, Solution::count_special_numbers(20)); + assert_eq!(5, Solution::count_special_numbers(5)); + assert_eq!(110, Solution::count_special_numbers(135)); + } +}