#![allow(unused, non_snake_case, dead_code, non_upper_case_globals)]
use {
    proconio::{marker::*, *},
    std::{cmp::*, collections::*, mem::*},
};

#[fastout]
fn main() {
    input! {//
        n:usize,k:usize,
    }
    let mut dp = vec![vec![vec![ModInt::new(0, MOD); 3333]; 55]; 55];
    dp[0][0][0] = ModInt::new(1, MOD);
    for i in 0..n {
        for rest in 0..n {
            for k in 0..=k {
                let ad = dp[i][rest][k];
                dp[i + 1][rest + 1][k + 2 * rest + 2] += ad;
                if rest > 0 {
                    dp[i + 1][rest][k + 2 * rest] += ad * ModInt::new(2 * rest as i64, MOD);
                }
                dp[i + 1][rest][k + 2 * rest] += ad;
                if rest > 0 {
                    dp[i + 1][rest - 1][k + 2 * rest - 2] +=
                        ad * ModInt::new((rest * rest) as i64, MOD);
                }
            }
        }
    }
    println!("{}", dp[n][0][k].value());
}
const MOD: i64 = 1000000007;
use std::ops::{
    Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, RemAssign, ShrAssign, Sub, SubAssign,
};
pub struct ModInt<T> {
    v: T,
    m: T,
}
impl<T> ModInt<T>
where
    T: Copy,
{
    pub fn value(&self) -> T {
        self.v
    }
    pub fn modulo(&self) -> T {
        self.m
    }
}
impl<T> ModInt<T> {
    fn new_unchecked(v: T, modulo: T) -> Self {
        Self { v, m: modulo }
    }
}
impl<T> ModInt<T>
where
    T: Copy + RemAssign + PartialOrd,
{
    pub fn new(mut v: T, modulo: T) -> Self {
        if v >= modulo {
            v %= modulo;
        }
        Self::new_unchecked(v, modulo)
    }
}
impl<T> ModInt<T>
where
    T: Copy
        + Sub<Output = T>
        + ShrAssign
        + BitAnd<Output = T>
        + PartialEq
        + PartialOrd
        + Div<Output = T>
        + RemAssign,
    ModInt<T>: MulAssign,
{
    pub fn pow(self, e: T) -> Self {
        let zero = self.modulo() - self.modulo();
        let one = self.modulo() / self.modulo();
        let mut e = e;
        let mut result = Self::new_unchecked(one, self.modulo());
        let mut cur = self;
        while e > zero {
            if e & one == one {
                result *= cur;
            }
            e >>= one;
            cur *= cur;
        }
        result
    }
}
impl<T> Copy for ModInt<T> where T: Copy {}
impl<T> Clone for ModInt<T>
where
    T: Copy,
{
    fn clone(&self) -> Self {
        Self::new_unchecked(self.value(), self.modulo())
    }
}
impl<T> Add<T> for ModInt<T>
where
    T: AddAssign + SubAssign + RemAssign + Copy + PartialOrd,
{
    type Output = Self;
    fn add(self, mut rhs: T) -> Self::Output {
        if rhs >= self.modulo() {
            rhs %= self.modulo();
        }
        rhs += self.value();
        if rhs >= self.modulo() {
            rhs -= self.modulo();
        }
        Self::new_unchecked(rhs, self.modulo())
    }
}
impl<T> Sub<T> for ModInt<T>
where
    T: AddAssign + SubAssign + RemAssign + Copy + PartialOrd,
{
    type Output = Self;
    fn sub(self, mut rhs: T) -> Self::Output {
        if rhs >= self.modulo() {
            rhs %= self.modulo();
        }
        let mut result = self.value();
        result += self.modulo();
        result -= rhs;
        if result >= self.modulo() {
            result -= self.modulo();
        }
        Self::new_unchecked(result, self.modulo())
    }
}
impl<T> Mul<T> for ModInt<T>
where
    T: MulAssign + RemAssign + Copy + PartialOrd,
{
    type Output = Self;
    fn mul(self, mut rhs: T) -> Self::Output {
        if rhs >= self.modulo() {
            rhs %= self.modulo();
        }
        rhs *= self.value();
        rhs %= self.modulo();
        Self::new_unchecked(rhs, self.modulo())
    }
}
impl<T> Add<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Add<T, Output = ModInt<T>>,
{
    type Output = Self;
    fn add(self, rhs: ModInt<T>) -> Self::Output {
        self + rhs.value()
    }
}
impl<T> Sub<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Sub<T, Output = ModInt<T>>,
{
    type Output = Self;
    fn sub(self, rhs: ModInt<T>) -> Self::Output {
        self - rhs.value()
    }
}
impl<T> Mul<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Mul<T, Output = ModInt<T>>,
{
    type Output = Self;
    fn mul(self, rhs: ModInt<T>) -> Self::Output {
        self * rhs.value()
    }
}
impl<T> Div<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Div<T, Output = ModInt<T>>,
{
    type Output = Self;
    fn div(self, rhs: ModInt<T>) -> Self::Output {
        self / rhs.value()
    }
}
impl<T> AddAssign<T> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Add<T, Output = ModInt<T>>,
{
    fn add_assign(&mut self, other: T) {
        *self = *self + other;
    }
}
impl<T> AddAssign<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Add<ModInt<T>, Output = ModInt<T>>,
{
    fn add_assign(&mut self, other: ModInt<T>) {
        *self = *self + other;
    }
}
impl<T> SubAssign<T> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Sub<T, Output = ModInt<T>>,
{
    fn sub_assign(&mut self, other: T) {
        *self = *self - other;
    }
}
impl<T> SubAssign<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Sub<ModInt<T>, Output = ModInt<T>>,
{
    fn sub_assign(&mut self, other: ModInt<T>) {
        *self = *self - other;
    }
}
impl<T> DivAssign<T> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Div<T, Output = ModInt<T>>,
{
    fn div_assign(&mut self, rhs: T) {
        *self = *self / rhs
    }
}
impl<T> DivAssign<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Div<ModInt<T>, Output = ModInt<T>>,
{
    fn div_assign(&mut self, rhs: ModInt<T>) {
        *self = *self / rhs
    }
}
impl<T> MulAssign<T> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Mul<T, Output = ModInt<T>>,
{
    fn mul_assign(&mut self, rhs: T) {
        *self = *self * rhs;
    }
}
impl<T> MulAssign<ModInt<T>> for ModInt<T>
where
    T: Copy,
    ModInt<T>: Mul<ModInt<T>, Output = ModInt<T>>,
{
    fn mul_assign(&mut self, rhs: ModInt<T>) {
        *self = *self * rhs;
    }
}
impl<T> Div<T> for ModInt<T>
where
    T: Copy
        + Add<Output = T>
        + Sub<Output = T>
        + Div<Output = T>
        + BitAnd<Output = T>
        + PartialEq
        + PartialOrd
        + ShrAssign
        + RemAssign
        + MulAssign,
{
    type Output = Self;
    fn div(self, mut rhs: T) -> Self::Output {
        if rhs >= self.modulo() {
            rhs %= self.modulo();
        }
        let one = self.modulo() / self.modulo();
        let two = one + one;
        self * Self::new_unchecked(rhs, self.modulo()).pow(self.modulo() - two)
    }
}


Measured memory_bytes: 159652