From 3690c3ab5e8fddf157e2debbfeae50266002790f Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sun, 3 Dec 2023 11:17:29 +0800 Subject: [PATCH] Add problem 1680: Concatenation of Consecutive Binary Numbers --- src/lib.rs | 1 + .../matrix_multiplication.rs | 85 +++++++++++++++++++ .../mod.rs | 83 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 src/problem_1680_concatenation_of_consecutive_binary_numbers/matrix_multiplication.rs create mode 100644 src/problem_1680_concatenation_of_consecutive_binary_numbers/mod.rs diff --git a/src/lib.rs b/src/lib.rs index ebddb85f..72e16f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1256,6 +1256,7 @@ pub mod problem_1674_minimum_moves_to_make_array_complementary; pub mod problem_1675_minimize_deviation_in_array; pub mod problem_1678_goal_parser_interpretation; pub mod problem_1679_max_number_of_k_sum_pairs; +pub mod problem_1680_concatenation_of_consecutive_binary_numbers; pub mod problem_1681_minimum_incompatibility; pub mod problem_1684_count_the_number_of_consistent_strings; pub mod problem_1685_sum_of_absolute_differences_in_a_sorted_array; diff --git a/src/problem_1680_concatenation_of_consecutive_binary_numbers/matrix_multiplication.rs b/src/problem_1680_concatenation_of_consecutive_binary_numbers/matrix_multiplication.rs new file mode 100644 index 00000000..054dd498 --- /dev/null +++ b/src/problem_1680_concatenation_of_consecutive_binary_numbers/matrix_multiplication.rs @@ -0,0 +1,85 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +// ⎡ f(n + 1) ⎤ ⎡ 1 << bits(n + 1) 1 1 ⎤ ⎡ f(n) ⎤ +// ⎢ n + 1 ⎥ = ⎢ 0 1 1 ⎥ ⎢ n ⎥ +// ⎣ 0 ⎦ ⎣ 0 0 1 ⎦ ⎣ 1 ⎦ + +impl Solution { + const MODULUS: u64 = 1_000_000_007; + + fn mul(x: (u64, u64, u64, u64), y: (u64, u64, u64, u64)) -> (u64, u64, u64, u64) { + ( + (x.0 * y.0) % Self::MODULUS, + (x.0 * y.1 + x.1) % Self::MODULUS, + (x.0 * y.2 + x.1 * y.3 + x.2) % Self::MODULUS, + x.3 + y.3, + ) + } + + fn square(x: (u64, u64, u64, u64)) -> (u64, u64, u64, u64) { + Self::mul(x, x) + } + + fn pow(mut base: (u64, u64, u64, u64), mut exponent: u32) -> (u64, u64, u64, u64) { + let mut result = (1, 0, 0, 0); + + while exponent != 0 { + if exponent & 1 != 0 { + result = Self::mul(base, result); + } + + base = Self::square(base); + exponent >>= 1; + } + + result + } + + fn apply(matrix: (u64, u64, u64, u64), state: (u64, u64)) -> u64 { + (matrix.0 * state.0 + matrix.1 * state.1 + matrix.2) % Self::MODULUS + } + + pub fn concatenated_binary(n: i32) -> i32 { + let n = n as u32; + let total_bits = 32 - n.leading_zeros(); + let mut result = 0; + + // Concatenate numbers in `1..(1 << (total_bits - 1))`. + + for bits in 1..total_bits { + let mut matrix = (1 << bits, 1, 1, 1); + + for _ in 1..bits { + matrix = Self::square(matrix); + } + + result = Self::apply(matrix, (result, (1 << (bits - 1)) - 1)); + } + + // Concatenate numbers in `(1 << (total_bits - 1))..=n`. + + let matrix = Self::pow((1 << total_bits, 1, 1, 1), n - (1 << (total_bits - 1)) + 1); + + result = Self::apply(matrix, (result, (1 << (total_bits - 1)) - 1)); + + result as _ + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn concatenated_binary(n: i32) -> i32 { + Self::concatenated_binary(n) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_1680_concatenation_of_consecutive_binary_numbers/mod.rs b/src/problem_1680_concatenation_of_consecutive_binary_numbers/mod.rs new file mode 100644 index 00000000..e43554cb --- /dev/null +++ b/src/problem_1680_concatenation_of_consecutive_binary_numbers/mod.rs @@ -0,0 +1,83 @@ +pub mod matrix_multiplication; + +pub trait Solution { + fn concatenated_binary(n: i32) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + // See + let test_cases = [ + (1, 1), + (2, 6), + (3, 27), + (4, 220), + (5, 1_765), + (6, 14_126), + (7, 113_015), + (8, 1_808_248), + (9, 28_931_977), + (10, 462_911_642), + (11, 406_586_234), + (12, 505_379_714), + (13, 86_075_381), + (14, 377_206_103), + (15, 35_297_621), + (16, 129_523_881), + (17, 144_764_181), + (18, 632_453_782), + (19, 238_520_903), + (20, 632_668_867), + (21, 245_403_625), + (22, 852_915_973), + (23, 293_310_970), + (24, 385_951_001), + (25, 350_431_973), + (26, 213_823_085), + (27, 842_338_705), + (28, 954_838_406), + (29, 554_828_811), + (30, 754_521_863), + (31, 144_699_479), + (32, 260_766_625), + (33, 689_063_921), + (34, 100_090_670), + (35, 405_802_873), + (36, 971_383_733), + (37, 168_558_515), + (38, 787_744_928), + (39, 415_675_081), + (40, 603_205_042), + (41, 605_122_463), + (42, 727_837_408), + (43, 581_593_833), + (44, 222_005_097), + (45, 208_326_155), + (46, 332_873_875), + (47, 303_927_900), + (48, 451_385_515), + (49, 888_672_813), + (50, 875_059_690), + (51, 3_819_819), + (52, 244_468_468), + (53, 645_981_900), + (54, 342_841_367), + (55, 941_847_396), + (56, 278_232_980), + (57, 806_910_658), + (58, 642_281_813), + (59, 106_035_804), + (60, 786_291_474), + (61, 322_654_047), + (62, 649_858_930), + (63, 590_971_296), + ]; + + for (n, expected) in test_cases { + assert_eq!(S::concatenated_binary(n), expected); + } + } +}