/// Имеется прямоугольное поле размера `n \times m`. Нужно посчитать число способов замостить его
/// доминошками размера `1 \times 2`. Доминошки могут быть повернуты горизонтально или вертикально,
/// но они не должны перекрываться или выходить за пределы поля. Поскольку ответ может быть
/// достаточно большим, требуется вывести его по модулю `k` (остаток от деления ответа на `k`).
pub fn solve() {
let m: u32 = 16;
let n: u32 = 16;
let bound: u64 = 1_000_000_000;
let mut d = vec![0u64; 2_u32.pow(m) as usize];
d[0] = 1;
// optimized to the left shifts
let pow2_m2 = 2_u32.pow(m - 2);
let pow2_m1 = 2_u32.pow(m - 1);
for _ in 0..n {
for i in 0..m - 1 {
for k in 0..pow2_m2 {
let k0 = insert_00(i, k);
let t = 1 << i;
let k1 = k0 + t;
let k2 = k1 + t;
let k3 = k2 + t;
d.swap(k0, k1);
d.swap(k2, k3);
d[k2] += d[k1];
d[k2] %= bound;
}
}
for k in 0..pow2_m1 {
let k0 = k as usize;
let k1 = k0 + pow2_m1 as usize;
d.swap(k0, k1);
}
}
println!("m = {}, n = {}, d = {}", m, n, d[0]);
}
/// функция вставляет два нулевых бита в позицию i,
/// пример для k == 63 и i == 0, 1, ... , 6
/// 11111100
/// 11111001
/// 11110011
/// 11100111
/// 11001111
/// 10011111
/// 00111111
fn insert_00(i: u32, k: u32) -> usize {
let mut x = k.clone();
let mut y = k.clone();
x <<= 2;
x &= (3_u32 << i).not();
x &= 0_u32.not() << i;
y &= (0_u32.not() << i).not();
x |= y;
x as usize
}
Comments
0 B
|👍
/👎
0 B
|👍
/👎