Skip to content

Commit

Permalink
Add problem 1680: Concatenation of Consecutive Binary Numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Dec 3, 2023
1 parent dfb6ee6 commit 3690c3a
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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::<super::Solution>();
}
}
Original file line number Diff line number Diff line change
@@ -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<S: Solution>() {
// See <https://oeis.org/A047778>
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);
}
}
}

0 comments on commit 3690c3a

Please sign in to comment.