Problem:
Score : 600 points

Problem Statement

Let us define the oddness of a permutation p = {p_1,\ p_2,\ ...,\ p_n} of {1,\ 2,\ ...,\ n} as \sum_{i = 1}^n |i - p_i|.

Find the number of permutations of {1,\ 2,\ ...,\ n} of oddness k, modulo 10^9+7.

Constraints

All values in input are integers.

1 \leq n \leq 50

0 \leq k \leq n^2

Input

Input is given from Standard Input in the following format:

n k

Output

Print the number of permutations of {1,\ 2,\ ...,\ n} of oddness k, modulo 10^9+7.

Sample Input 1

3 2

Sample Output 1

2

There are six permutations of {1,\ 2,\ 3}. Among them, two have oddness of 2: {2,\ 1,\ 3} and {1,\ 3,\ 2}.

Sample Input 2

39 14

Sample Output 2

74764168

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::prelude::*;

fn input<T: std::str::FromStr>() -> T {
    let stdin = std::io::stdin();
    let token: String = stdin
        .lock()
        .bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().unwrap()
}

fn main() {
    let n: usize = input();
    let k: usize = input();

    let mut dp = vec![vec![vec![ModInt(0); k + 1]; n + 1]; n + 1];
    dp[0][0][0] += 1;
    for i in 0..n {
        for j in 0..i + 1 {
            for s in 0..k + 1 {
                let nj = j;
                if s + nj * 2 <= k {
                    let t = dp[i][j][s];
                    dp[i + 1][nj][s + nj * 2] += t;
                }

                let nj = j + 1;
                if s + nj * 2 <= k {
                    let t = dp[i][j][s];
                    dp[i + 1][nj][s + nj * 2] += t;
                }

                let nj = j;
                if s + nj * 2 <= k {
                    let t = dp[i][j][s] * 2 * j as i64;
                    dp[i + 1][nj][s + nj * 2] += t;
                }

                if j > 0 {
                    let nj = j - 1;
                    if s + nj * 2 <= k {
                        let t = dp[i][j][s] * j as i64 * j as i64;
                        dp[i + 1][nj][s + nj * 2] += t;
                    }
                }
            }
        }
    }

    println!("{}", dp[n][0][k]);
}

const MOD: i64 = 1000000007;

#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct ModInt(i64);

impl ModInt {
    fn new(x: i64) -> ModInt {
        ModInt(if x < MOD { x } else { x % MOD })
    }
}

impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl std::ops::AddAssign<ModInt> for ModInt {
    fn add_assign(&mut self, other: ModInt) {
        self.0 += other.0;
        if self.0 >= MOD {
            self.0 -= MOD;
        }
    }
}

impl std::ops::MulAssign<ModInt> for ModInt {
    fn mul_assign(&mut self, other: ModInt) {
        self.0 *= other.0;
        if self.0 >= MOD {
            self.0 %= MOD;
        }
    }
}

impl std::ops::SubAssign<ModInt> for ModInt {
    fn sub_assign(&mut self, other: ModInt) {
        self.0 += MOD - other.0;
        if self.0 >= MOD {
            self.0 -= MOD;
        }
    }
}

macro_rules! impl_modint_assign_op_ref {
    ($imp:ident, $method:ident) => {
        impl<'a> std::ops::$imp<&'a ModInt> for ModInt {
            fn $method(&mut self, other: &'a ModInt) {
                std::ops::$imp::$method(self, *other);
            }
        }
    };
}

impl_modint_assign_op_ref!(AddAssign, add_assign);
impl_modint_assign_op_ref!(MulAssign, mul_assign);
impl_modint_assign_op_ref!(SubAssign, sub_assign);

macro_rules! impl_modint_op {
    ($imp:ident, $method:ident, $assign_t:ident, $assign_m:ident) => {
        impl std::ops::$imp<ModInt> for ModInt {
            type Output = ModInt;

            fn $method(self, other: ModInt) -> ModInt {
                let mut x = self;
                std::ops::$assign_t::$assign_m(&mut x, other);
                x
            }
        }
    };
}

impl_modint_op!(Add, add, AddAssign, add_assign);
impl_modint_op!(Mul, mul, MulAssign, mul_assign);
impl_modint_op!(Sub, sub, SubAssign, sub_assign);

macro_rules! impl_modint_op_ref {
    ($imp:ident, $method:ident) => {
        impl<'a> std::ops::$imp<ModInt> for &'a ModInt {
            type Output = ModInt;

            fn $method(self, other: ModInt) -> ModInt {
                std::ops::$imp::$method(*self, other)
            }
        }

        impl<'a> std::ops::$imp<&'a ModInt> for ModInt {
            type Output = ModInt;

            fn $method(self, other: &'a ModInt) -> ModInt {
                std::ops::$imp::$method(self, *other)
            }
        }

        impl<'a, 'b> std::ops::$imp<&'b ModInt> for &'a ModInt {
            type Output = ModInt;

            fn $method(self, other: &'b ModInt) -> ModInt {
                std::ops::$imp::$method(*self, *other)
            }
        }
    };
}

impl_modint_op_ref!(Add, add);
impl_modint_op_ref!(Mul, mul);
impl_modint_op_ref!(Sub, sub);

macro_rules! impl_modint_op_i64 {
    ($imp:ident, $method:ident) => {
        impl<T: Into<i64>> std::ops::$imp<T> for ModInt {
            type Output = ModInt;

            fn $method(self, other: T) -> ModInt {
                std::ops::$imp::$method(self, ModInt::new(other.into()))
            }
        }
    };
}

impl_modint_op_i64!(Add, add);
impl_modint_op_i64!(Mul, mul);
impl_modint_op_i64!(Sub, sub);

macro_rules! impl_modint_assign_op_i64 {
    ($imp:ident, $method:ident) => {
        impl<T: Into<i64>> std::ops::$imp<T> for ModInt {
            fn $method(&mut self, other: T) {
                std::ops::$imp::$method(self, ModInt::new(other.into()));
            }
        }
    };
}

impl_modint_assign_op_i64!(AddAssign, add_assign);
impl_modint_assign_op_i64!(MulAssign, mul_assign);
impl_modint_assign_op_i64!(SubAssign, sub_assign);

macro_rules! impl_modint_accum {
    ($imp:ident, $method:ident, $e:expr, $op_t:ident, $op_m:ident) => {
        impl std::iter::$imp for ModInt {
            fn $method<I: Iterator<Item = ModInt>>(iter: I) -> ModInt {
                iter.fold(ModInt($e), std::ops::$op_t::$op_m)
            }
        }

        impl<'a> std::iter::$imp<&'a ModInt> for ModInt {
            fn $method<I: Iterator<Item = &'a ModInt>>(iter: I) -> ModInt {
                iter.fold(ModInt($e), std::ops::$op_t::$op_m)
            }
        }
    };
}

impl_modint_accum!(Sum, sum, 0, Add, add);
impl_modint_accum!(Product, product, 1, Mul, mul);