// Original C++ solution (slower):
#include <bits/stdc++.h>

#include <cassert>

typedef long long int ll;

using namespace std;



// @@ !! LIM(mod debug debug)

// --> f:gcd mod f:<< debug

// ---- inserted function gcd from util.cc

// g = eGCD(a, b, s, t)  --->  sa + tb = g

constexpr ll eGCD(ll a, ll b, ll& s, ll& t) {

  if (a == 0) {

    s = 0;

    t = 1;

    return b;

  }

  ll u = 0;

  ll g = eGCD(b % a, a, t, u);

  s = u - (b / a) * t;

  return g;

}



constexpr ll gcd(ll a, ll b) {

  ll dummy1 = 0;

  ll dummy2 = 0;

  return eGCD(a, b, dummy1, dummy2);

}

// ---- end gcd

// ---- inserted library file mod.cc



ll MOD = 1e9 + 7;

// ll MOD = 998244353;



struct Fp {

  ll val;



  Fp(ll t = 0) {

    if      (t >= MOD)  val = t % MOD;

    else if (t >= 0)    val = t;

    else if (t >= -MOD) val = t + MOD;

    else {

      ll v = t % MOD;

      if (v == 0) val = 0;

      else        val = v + MOD;

    }

  }



  Fp& operator +=(const Fp& t) {

    val += t.val;

    if (val >= MOD) val -= MOD;

    return *this;

  }



  Fp& operator -=(const Fp& t) {

    val -= t.val;

    if (val < 0) val += MOD;

    return *this;

  }



  Fp& operator *=(const Fp& t) {

    val = (val * t.val) % MOD;

    return *this;

  }



  Fp inv() const {

    if (val == 0) {

      cerr << "inv() is called for zero." << endl;

      exit(1);

    }

    ll u = 0;

    ll v = 0;

    eGCD(val, MOD, u, v);

    return Fp(u);

  }



  Fp& operator /=(const Fp& t) {

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

  }



  Fp operator +(const Fp& t) const { return Fp(val) += t; }

  Fp operator -(const Fp& t) const { return Fp(val) -= t; }

  Fp operator *(const Fp& t) const { return Fp(val) *= t; }

  Fp operator /(const Fp& t) const { return Fp(val) /= t; }

  Fp operator -() const { return Fp(-val); }



  bool operator ==(const Fp& t) const { return val == t.val; }

  bool operator !=(const Fp& t) const { return val != t.val; }

  

  operator ll() const { return val; }



};



class Comb {

  int nMax;

  vector<Fp> vFact;

  vector<Fp> vInvFact;

public:

  Comb(int nm) : nMax(nm), vFact(nm+1), vInvFact(nm+1) {

    vFact.at(0) = 1;

    for (int i = 1; i <= nMax; i++) vFact.at(i) = i * vFact.at(i-1);

    vInvFact.at(nMax) = vFact.at(nMax).inv();

    for (int i = nMax; i >= 1; i--) vInvFact.at(i-1) = i * vInvFact.at(i);

  }

  Fp fact(int n) { return vFact.at(n); }

  Fp comb(int n, int r) {

    return vFact.at(n) * vInvFact.at(r) * vInvFact.at(n-r);

  }

  // The number of permutation extracting r from n.

  Fp perm(int n, int r) {

    return vFact.at(n) * vInvFact.at(n-r);

  }

};



// ---- end mod.cc

// ---- inserted function << from util.cc

template <typename T1, typename T2>

ostream& operator<< (ostream& os, const pair<T1,T2>& p) {

  os << "(" << p.first << ", " << p.second << ")";

  return os;

}



template <typename T1, typename T2, typename T3>

ostream& operator<< (ostream& os, const tuple<T1,T2,T3>& t) {

  os << "(" << get<0>(t) << ", " << get<1>(t)

     << ", " << get<2>(t) << ")";

  return os;

}



template <typename T1, typename T2, typename T3, typename T4>

ostream& operator<< (ostream& os, const tuple<T1,T2,T3,T4>& t) {

  os << "(" << get<0>(t) << ", " << get<1>(t)

     << ", " << get<2>(t) << ", " << get<3>(t) << ")";

  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const vector<T>& v) {

  os << '[';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << ']';



  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const set<T>& v) {

  os << '{';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << '}';



  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const multiset<T>& v) {

  os << '{';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << '}';



  return os;

}



template <typename T1, typename T2>

ostream& operator<< (ostream& os, const map<T1, T2>& mp) {

  os << '[';

  for (auto it = mp.begin(); it != mp.end(); it++) {

    if (it != mp.begin()) os << ", ";

    os << it->first << ": " << it->second;

  }

  os << ']';



  return os;

}



template <typename T, typename T2, typename T3>

ostream& operator<< (ostream& os, const priority_queue<T, T2, T3>& orig) {

  priority_queue<T, T2, T3> pq(orig);

  bool first = true;

  os << '[';

  while (!pq.empty()) {

    T x = pq.top(); pq.pop();

    if (!first) os << ", ";

    os << x;

    first = false;

  }

  return os << ']';

}

// ---- end <<

// ---- inserted library file debug.cc

template <class... Args>

string dbgFormat(const char* fmt, Args... args) {

  size_t len = snprintf(nullptr, 0, fmt, args...);

  char buf[len + 1];

  snprintf(buf, len + 1, fmt, args...);

  return string(buf);

}



template <class Head>

void dbgLog(Head&& head) {

  cerr << head << endl;

}



template <class Head, class... Tail>

void dbgLog(Head&& head, Tail&&... tail)

{

  cerr << head << " ";

  dbgLog(forward<Tail>(tail)...);

}



#if DEBUG

  #define DLOG(...)        dbgLog(__VA_ARGS__)

  #define DFMT(...)        cerr << dbgFormat(__VA_ARGS__) << endl

  #define DCALL(func, ...) func(__VA_ARGS__)

#else

  #define DLOG(...)

  #define DFMT(...)

  #define DCALL(func, ...)

#endif



// ---- end debug.cc

// @@ !! LIM  -- end mark --



using Vec1 = vector<Fp>;

using Vec2 = vector<Vec1>;

using Vec3 = vector<Vec2>;



int main(int argc, char *argv[]) {

  ios_base::sync_with_stdio(false);

  cin.tie(nullptr);

  cout << setprecision(20);



  ll N, K; cin >> N >> K;

  Vec3 tbl(N+1, Vec2(N+1, Vec1(N*N + 1)));

  tbl.at(0).at(0).at(0) = 1;

  for (ll i = 0; i < N; i++) {

    const auto& prev = tbl.at(i);

    auto& cur = tbl.at(i+1);

    for (ll j = 0; j <= N; j++) {

      for (ll k = 0; k <= N*N; k++) {

	auto upd = [&](ll jj, ll dk, ll n) -> void {

	  if (0 <= jj && jj <= N && k + dk <= N*N) {

	    cur.at(jj).at(k + dk) += Fp(n) * prev.at(j).at(k);

	    // DLOG("cur upd", jj, k+dk, Fp(n), prev.at(j).at(k));

	  }

	};

	// append * 

	// DLOG("upd1", j+1, k+2*(j+1));

	upd(j+1, 2*(j+1), 1);

	// append num

	upd(j, 2*j, j + 1);

	// append *, place i+1

	upd(j, 2*j, j);

	// append num, place i+1

	upd(j-1, 2*(j-1), j*j);

      }

    }

#ifdef DEBUG    

    DLOG("i", i);

    for (ll j = 0; j < N+1; j++) {

      DLOG("  j", j, tbl.at(i+1).at(j));

    }

#endif

  }

  cout << tbl.at(N).at(0).at(K) << endl;



  return 0;

}




// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#include <cassert>

typedef long long int ll;

using namespace std;



// @@ !! LIM(mod debug debug)

// --> f:gcd mod f:<< debug

// ---- inserted function gcd from util.cc

// g = eGCD(a, b, s, t)  --->  sa + tb = g

constexpr ll eGCD(ll a, ll b, ll& s, ll& t) {

  if (a == 0) {

    s = 0;

    t = 1;

    return b;

  }

  ll u = 0;

  ll g = eGCD(b % a, a, t, u);

  s = u - (b / a) * t;

  return g;

}



constexpr ll gcd(ll a, ll b) {

  ll dummy1 = 0;

  ll dummy2 = 0;

  return eGCD(a, b, dummy1, dummy2);

}

// ---- end gcd

// ---- inserted library file mod.cc



ll MOD = 1e9 + 7;

// ll MOD = 998244353;



struct Fp {

  ll val;



  Fp(ll t = 0) {

    if      (t >= MOD)  val = t % MOD;

    else if (t >= 0)    val = t;

    else if (t >= -MOD) val = t + MOD;

    else {

      ll v = t % MOD;

      if (v == 0) val = 0;

      else        val = v + MOD;

    }

  }



  Fp& operator +=(const Fp& t) {

    val += t.val;

    if (val >= MOD) val -= MOD;

    return *this;

  }



  Fp& operator -=(const Fp& t) {

    val -= t.val;

    if (val < 0) val += MOD;

    return *this;

  }



  Fp& operator *=(const Fp& t) {

    val = (val * t.val) % MOD;

    return *this;

  }



  Fp inv() const {

    if (val == 0) {

      cerr << "inv() is called for zero." << endl;

      exit(1);

    }

    ll u = 0;

    ll v = 0;

    eGCD(val, MOD, u, v);

    return Fp(u);

  }



  Fp& operator /=(const Fp& t) {

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

  }



  Fp operator +(const Fp& t) const { return Fp(val) += t; }

  Fp operator -(const Fp& t) const { return Fp(val) -= t; }

  Fp operator *(const Fp& t) const { return Fp(val) *= t; }

  Fp operator /(const Fp& t) const { return Fp(val) /= t; }

  Fp operator -() const { return Fp(-val); }



  bool operator ==(const Fp& t) const { return val == t.val; }

  bool operator !=(const Fp& t) const { return val != t.val; }

  

  operator ll() const { return val; }



};



class Comb {

  int nMax;

  vector<Fp> vFact;

  vector<Fp> vInvFact;

public:

  Comb(int nm) : nMax(nm), vFact(nm+1), vInvFact(nm+1) {

    vFact.at(0) = 1;

    for (int i = 1; i <= nMax; i++) vFact.at(i) = i * vFact.at(i-1);

    vInvFact.at(nMax) = vFact.at(nMax).inv();

    for (int i = nMax; i >= 1; i--) vInvFact.at(i-1) = i * vInvFact.at(i);

  }

  Fp fact(int n) { return vFact.at(n); }

  Fp comb(int n, int r) {

    return vFact.at(n) * vInvFact.at(r) * vInvFact.at(n-r);

  }

  // The number of permutation extracting r from n.

  Fp perm(int n, int r) {

    return vFact.at(n) * vInvFact.at(n-r);

  }

};



// ---- end mod.cc

// ---- inserted function << from util.cc

template <typename T1, typename T2>

ostream& operator<< (ostream& os, const pair<T1,T2>& p) {

  os << "(" << p.first << ", " << p.second << ")";

  return os;

}



template <typename T1, typename T2, typename T3>

ostream& operator<< (ostream& os, const tuple<T1,T2,T3>& t) {

  os << "(" << get<0>(t) << ", " << get<1>(t)

     << ", " << get<2>(t) << ")";

  return os;

}



template <typename T1, typename T2, typename T3, typename T4>

ostream& operator<< (ostream& os, const tuple<T1,T2,T3,T4>& t) {

  os << "(" << get<0>(t) << ", " << get<1>(t)

     << ", " << get<2>(t) << ", " << get<3>(t) << ")";

  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const vector<T>& v) {

  os << '[';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << ']';



  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const set<T>& v) {

  os << '{';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << '}';



  return os;

}



template <typename T>

ostream& operator<< (ostream& os, const multiset<T>& v) {

  os << '{';

  for (auto it = v.begin(); it != v.end(); it++) {

    if (it != v.begin()) os << ", ";

    os << *it;

  }

  os << '}';



  return os;

}



template <typename T1, typename T2>

ostream& operator<< (ostream& os, const map<T1, T2>& mp) {

  os << '[';

  for (auto it = mp.begin(); it != mp.end(); it++) {

    if (it != mp.begin()) os << ", ";

    os << it->first << ": " << it->second;

  }

  os << ']';



  return os;

}



template <typename T, typename T2, typename T3>

ostream& operator<< (ostream& os, const priority_queue<T, T2, T3>& orig) {

  priority_queue<T, T2, T3> pq(orig);

  bool first = true;

  os << '[';

  while (!pq.empty()) {

    T x = pq.top(); pq.pop();

    if (!first) os << ", ";

    os << x;

    first = false;

  }

  return os << ']';

}

// ---- end <<

// ---- inserted library file debug.cc

template <class... Args>

string dbgFormat(const char* fmt, Args... args) {

  size_t len = snprintf(nullptr, 0, fmt, args...);

  char buf[len + 1];

  snprintf(buf, len + 1, fmt, args...);

  return string(buf);

}



template <class Head>

void dbgLog(Head&& head) {

  cerr << head << endl;

}



template <class Head, class... Tail>

void dbgLog(Head&& head, Tail&&... tail)

{

  cerr << head << " ";

  dbgLog(forward<Tail>(tail)...);

}



#if DEBUG

  #define DLOG(...)        dbgLog(__VA_ARGS__)

  #define DFMT(...)        cerr << dbgFormat(__VA_ARGS__) << endl

  #define DCALL(func, ...) func(__VA_ARGS__)

#else

  #define DLOG(...)

  #define DFMT(...)

  #define DCALL(func, ...)

#endif



// ---- end debug.cc

// @@ !! LIM  -- end mark --



using Vec1 = vector<Fp>;

using Vec2 = vector<Vec1>;

using Vec3 = vector<Vec2>;



int main(int argc, char *argv[]) {

  ios_base::sync_with_stdio(false);

  cin.tie(nullptr);

  cout << setprecision(20);



  ll N, K; cin >> N >> K;

  Vec3 tbl(N+1, Vec2(N+1, Vec1(K + 1)));

  tbl.at(0).at(0).at(0) = 1;

  for (ll i = 0; i < N; i++) {

    const auto& prev = tbl.at(i);

    auto& cur = tbl.at(i+1);

    for (ll j = 0; j <= i; j++) {

      for (ll k = 0; k <= K; k++) {

	auto upd = [&](ll jj, ll dk, ll n) -> void {

	  if (0 <= jj && jj <= N && k + dk <= K) {

	    cur.at(jj).at(k + dk) += Fp(n) * prev.at(j).at(k);

	    // DLOG("cur upd", jj, k+dk, Fp(n), prev.at(j).at(k));

	  }

	};

	// append * 

	// DLOG("upd1", j+1, k+2*(j+1));

	upd(j+1, 2*(j+1), 1);

	// append num  /and/  append *, place i+1

	upd(j, 2*j, 2 * j + 1);

	// append num, place i+1

	upd(j-1, 2*(j-1), j*j);

      }

    }

#ifdef DEBUG    

    DLOG("i", i);

    for (ll j = 0; j < N+1; j++) {

      DLOG("  j", j, tbl.at(i+1).at(j));

    }

#endif

  }

  cout << tbl.at(N).at(0).at(K) << endl;



  return 0;

}




// Fastest known solution for this problem: