// Slower C++ solution:
bool DBG = false;

#include<bits/stdc++.h>

//#include <boost/multiprecision/cpp_dec_float.hpp>

//#include <boost/multiprecision/cpp_int.hpp>

using namespace std;

using ll = long long;

using ld = long double;

//using i128 = __int128_t;

//using bint = boost::multiprecision::cpp_int

//using d1024 = boost::multiprecision::number<mp::cpp_dec_float<1024>>;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define IFOR(i,a,b) for(int i=(b-1);i>=(a);--i)

#define RPT(i,a,b) for(int i=(a);i<((a)+(b));++i)

#define IRPT(i,a,b) for(int i=((a)+(b)-1);i>=(a);--i)

#define ALL(x) x.begin(),x.end()

#define fs first

#define sd second

#define couts(x) cout << (x) << (" ")

#define coutn(x) cout << (x) << ("\n")

#define endl "\n"

#define pb push_back

#define eb emplace_back

#define lb lower_bound

#define ub upper_bound

#define dcouts(x) if(DBG) couts(x)

#define dcoutn(x) if(DBG) coutn(x);

template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec){ for (auto &v : vec) is >> v; return is; }

template<typename T1, typename T2> std::istream &operator>>(std::istream &is, std::pair<T1,T2> &p){is >> p.first >> p.second; return is; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::deque<T> &vec){ os << "deque["; for (auto v : vec) os << v << ","; os << "]"; return os; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }

template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }

template<typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }

template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }

template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }



template<class T> using V = vector<T>;

template<class T> using V2 = V<V<T>>;

template<class T> using V3 = V<V2<T>>;



constexpr ll mod = 1000000007;





/*void solve(){

  int n, k; cin >> n >> k;

  auto f = [&](V<int> &v){

    int ret = 0;

    FOR(i,0,(int)v.size()) ret += abs(i-v[i]);

    return ret;

  };

  V<int> a(n), b(n*n+1,0);

  FOR(i,0,n) a[i] = i;

  do{

    b[f(a)]++;

  }while(next_permutation(ALL(a)));

  while(*(b.end()-1)==0) b.pop_back();

  coutn(b[k]);

}*/



void solve(){

  int n, k; cin >> n >> k;

  V3<ll> dp(n+5, V2<ll>(n+5, V<ll>(n*n+5, 0))   );

  dp[0][0][0] = 1;

  FOR(i,1,n+1){

    FOR(j,0,n+1){

      FOR(l,0,n*n+1){

        if(l-2*j>=0)(dp[i][j][l]+=(2*j+1)*dp[i-1][j][l-2*j]%mod +(j+1)*(j+1)*dp[i-1][j+1][l-2*j]%mod ) %= mod;

        if(l-2*j>=0 && j>0) (dp[i][j][l] += dp[i-1][j-1][l-2*j])%= mod;

      }

    }

  }

  coutn(dp[n][0][k]);

  //coutn(dp);

}





int main(void){

  cin.tie(0);

  ios::sync_with_stdio(false);

  solve();

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 2.615346650239702x):
#include <bits/stdc++.h>

#define rep(i,n) for (int i = 0; i < (n); ++i)

using namespace std;

typedef long long ll;

template<class T> using V = vector<T>;

template<class T> using V2 = V<V<T>>;

template<class T> using V3 = V<V2<T>>;



// auto mod int

// https://youtu.be/L8grWxBlIZ4?t=9858

// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize

// https://youtu.be/8uowVvQ_-Mo?t=1329 : division

const int mod = 1000000007;

struct mint {

  ll x; // typedef long long ll;

  mint(ll x=0):x(x%mod){}

  mint& operator+=(const mint a) {

    if ((x += a.x) >= mod) x -= mod;

    return *this;

  }

  mint& operator-=(const mint a) {

    if ((x += mod-a.x) >= mod) x -= mod;

    return *this;

  }

  mint& operator*=(const mint a) {

    (x *= a.x) %= mod;

    return *this;

  }

  mint operator+(const mint a) const {

    mint res(*this);

    return res+=a;

  }

  mint operator-(const mint a) const {

    mint res(*this);

    return res-=a;

  }

  mint operator*(const mint a) const {

    mint res(*this);

    return res*=a;

  }

  mint pow(ll t) const {

    if (!t) return 1;

    mint a = pow(t>>1);

    a *= a;

    if (t&1) a *= *this;

    return a;

  }



  // for prime mod

  mint inv() const {

    return pow(mod-2);

  }

  mint& operator/=(const mint a) {

    return (*this) *= a.inv();

  }

  mint operator/(const mint a) const {

    mint res(*this);

    return res/=a;

  }

};





int main() {

  cin.tie(0);

  ios::sync_with_stdio(false);

  int n, score;

  cin >> n >> score;

  V2<mint> dp(n+5, V<mint>(score/2 + 50, 0) );

  dp[0][0] = 1;

  rep(i,n) {

    V2<mint> dp_pre(n+5, V<mint>(score/2+1 + 50, 0) );

    swap(dp, dp_pre);

    rep(j,i+1)rep(k,score/2+1) {

      {

        int nj = j;

        dp[nj][k+nj] += dp_pre[j][k];

      }

      {

        int nj = j+1;

        dp[nj][k+nj] += dp_pre[j][k];

      }

      {

        int nj = j;

        mint x = j*2;

        dp[nj][k+nj] += dp_pre[j][k]*x;

      }

      if (j >= 1) {

        int nj = j-1;

        mint x = j*j;

        dp[nj][k+nj] += dp_pre[j][k]*x;

      }

    }

  }

  mint ans = dp[0][score/2];

  if (score&1) ans = 0;

  cout << ans.x << endl;

  return 0;

}