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 (Python):
n, k = map(int, input().split())
MOD =10**9+7

memo = [[{} for j in  range(n+1)] for i in range(n+1)]

def fdp(cur_N, remain, min_k, MOD=10**9+7):
    if cur_N <= 1:
        if remain == 0 and min_k == 0:
            return 1
        if remain == 1 and min_k == 2:
            return 1
        else:
            return 0
    if cur_N < remain:
        return 0
    if min_k < 0:
        return 0
    if min_k in memo[cur_N][remain]:
        ret = memo[cur_N][remain][min_k]
        return ret
      
    temp1 = fdp(cur_N-1, remain, min_k - 2*remain) %MOD
    temp2 = fdp(cur_N-1, remain+1, min_k -2*remain) %MOD
    temp3 = fdp(cur_N-1, remain-1, min_k-2*remain) % MOD
    score = (temp1*(2*remain+1))%MOD +(temp2*(remain+1)*(remain+1))%MOD+temp3
    score = score % MOD
    memo[cur_N][remain][min_k] = score
    return score
ret = fdp(n, 0, k)
print(ret)

Solution (Python):
n, k = map(int, input().split())
MOD =10**9+7

memo = [[{} for j in  range(n+1)] for i in range(n+1)]

def fdp(cur_N, remain, min_k, MOD=10**9+7):
    if cur_N <= 1:
        if remain == 0 and min_k == 0:
            return 1
        if remain == 1 and min_k == 2:
            return 1
        else:
            return 0
    if min_k in memo[cur_N][remain]:
        ret = memo[cur_N][remain][min_k]
        return ret
    
    temp1 = fdp(cur_N-1, remain, min_k - 2*remain) %MOD
    temp2 = fdp(cur_N-1, remain+1, min_k -2*remain) %MOD
    temp3 = fdp(cur_N-1, remain-1, min_k-2*remain) % MOD
    score = (temp1*(2*remain+1))%MOD +(temp2*(remain+1)*(remain+1))%MOD+temp3
    score = score % MOD
    memo[cur_N][remain][min_k] = score
    return score
ret = fdp(n, 0, k)
print(ret)

Solution (Python):
mod = 10**9+7
N, K = map(int, input().split())
if K % 2:
    print(0)
else:
    dp = [[[0]*(2*N**2+2*N) for _ in range(N+1)] for _ in range(N+1)]
    dp[0][0][0] = 1
    for i in range(N):
        for k in range(i+2):
            for S in range(-N**2+1, N**2):
                d = dp[i][k][S]
                if not d:
                    continue
                dp[i+1][k][S] = (dp[i+1][k][S]+(2*k+1)*d)%mod
                dp[i+1][k+1][S-2*(i+1)] = (dp[i+1][k+1][S-2*(i+1)]+d)%mod
                dp[i+1][k-1][S+2*(i+1)] = (dp[i+1][k-1][S+2*(i+1)]+k*k*d)%mod
    print(dp[N][0][K])

Solution (Python):
n,k0=map(int,input().split())
mod=10**9+7



from collections import defaultdict

DP=defaultdict(int)
DP[0,0]=1

for i in range(n):
    NDP=defaultdict(int)

    for j,k in DP:
        l=DP[j,k]

        NDP[j,k+2*j]=(NDP[j,k+2*j]+l)%mod

        if j>=1:
            NDP[j,k+2*j]=(NDP[j,k+2*j]+2*j*l)%mod

        if j>=1:
            NDP[j-1,k+2*(j-1)]=(NDP[j-1,k+2*(j-1)]+j*j*l)%mod

        NDP[j+1,k+2*(j+1)]=(NDP[j+1,k+2*(j+1)]+l)%mod

    DP=NDP

ANS=0
for j,k in DP:
    if j==0 and k==k0:
        ANS+=DP[j,k]

print(ANS%mod)

Solution (Python):
import sys
stdin = sys.stdin

sys.setrecursionlimit(10 ** 7)

def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x) - 1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

n, k = li()
MOD = 10**9 + 7

dp = [[[0]*(n*n+1) for _ in range(n+1)] for _ in range(n+1)]

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

for x in range(1, n+1):
    for y in range(n+1):
        for z in range(n*n+1):
            dp[x][y][z] = ((2*y + 1) * dp[x-1][y][z-2*y] if z-2*y >= 0 else 0)\
                            + ((y+1)**2 * dp[x-1][y+1][z-2*y] if (z-2*y >= 0 and y+1 <= n) else 0)\
                            + (dp[x-1][y-1][z-2*y] if (z-2*y >= 0 and y-1 >= 0) else 0)
            dp[x][y][z] %= MOD

print(dp[n][0][k])

Solution (Python):
n, k = map(int, input().split())
dp = {}

dp[(0, 0, 0)] = 1

def perm(i, j, k):
  if (i, j, k) in dp:
    return dp[(i, j, k)]
  
  if i < 0 or j < 0 or k < 0:
    return 0
  
  dp[(i, j, k)] = ((j+j+1)*perm(i-1, j, k-2*j)\
                + (j+1)*(j+1)*perm(i-1, j+1, k-2*j)\
                +  1*perm(i-1, j-1, k-2*j))%(10**9+7)
  return dp[(i, j, k)]

print(perm(n, 0, k))

Solution (Python):
n, k = map(int, input().split())
dp = {}

dp[(0, 0, 0)] = 1

def perm(i, j, k):
  if (i, j, k) in dp:
    return dp[(i, j, k)]
  
  if i < 0 or j < 0 or k < 0 or i < j:
    return 0
  
  dp[(i, j, k)] = ((j+j+1)*perm(i-1, j, k-2*j)\
                + (j+1)*(j+1)*perm(i-1, j+1, k-2*j)\
                +  1*perm(i-1, j-1, k-2*j))%(10**9+7)
  return dp[(i, j, k)]

print(perm(n, 0, k))

Solution (Python):
n, k = map(int, input().split())
dp = {}

dp[(0, 0, 0)] = 1

def perm(i, j, k):
  if (i, j, k) in dp:
    return dp[(i, j, k)]
  
  if i == 0 and (j is not 0 or k is not 0):
    return 0
  
  if i < 0 or j < 0 or k < 0 or i < j:
    return 0
  
  dp[(i, j, k)] = ((j+j+1)*perm(i-1, j, k-2*j)\
                + (j+1)*(j+1)*perm(i-1, j+1, k-2*j)\
                +  1*perm(i-1, j-1, k-2*j))%(10**9+7)
  return dp[(i, j, k)]

print(perm(n, 0, k))

Solution (Python):
n, k = map(int, input().split())
dp = {}

dp[(0, 0, 0)] = 1

def perm(i, j, k):
  if (i, j, k) in dp:
    return dp[(i, j, k)]
  if i == 0:
      if k == 0 and j == 0:
          return 1
      else:
          return 0
  elif k < 0 or j < 0 or i < j:
      return 0
  else:
    dp[(i, j, k)] = ((j+j+1)*perm(i-1, j, k-2*j)\
                  + (j+1)*(j+1)*perm(i-1, j+1, k-2*j)\
                  +  1*perm(i-1, j-1, k-2*j))%(10**9+7)
    return dp[(i, j, k)]

print(perm(n, 0, k))

Solution (Python):
import sys


import sys
from collections import deque
sys.setrecursionlimit(10**7)
MOD = 10 ** 9 + 7
def LI(): return map(int, sys.stdin.readline().split())

def main():
    r = lambda: sys.stdin.readline().strip()
    R = lambda: list(map(int, r().split()))
    N, K = R()
    dp = [0]*2610*51*51
    ip = 2610*51
    restp = 2610
    dp[0] = 1
    for i in range(N):
        for rest in range(N):
            if rest > N //2:
                break
            for k in range(0, K+1, 2):                
                
                dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] += dp[i*ip+rest*restp+k]
                dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] %= MOD
                dp[(i+1)*ip+rest*restp+(k+2*rest)] += dp[i*ip+rest*restp+k] * (2*rest+1)
                dp[(i+1)*ip+rest*restp+(k+2*rest)] %= MOD
                if rest:
                    dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] += dp[i*ip+rest*restp+k] * rest * rest
                    dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] %= MOD
    print(dp[N*ip+K])

if __name__ == "__main__":
    main()

Solution (Python):
def main():

    """ convenient functions
    
    
    
    
    
    """

    """convenient decorator
    
    
        
        
        
        
        
        
        
        
        
        
    """
    
    
    import sys
    sys.setrecursionlimit(10**7)
    from itertools import accumulate, combinations, permutations, product 
    
    from math import factorial, ceil, floor, sqrt
    def factorize(n):
        """return the factors of the Arg and count of each factor
        
        Args:
            n (long): number to be resolved into factors
        
        Returns:
            list of tuples: factorize(220) returns [(2, 2), (5, 1), (11, 1)]
        """
        fct = []  
        b, e = 2, 0  
        while b * b <= n:
            while n % b == 0:
                n = n // b
                e = e + 1
            if e > 0:
                fct.append((b, e))
            b, e = b + 1, 0
        if n > 1:
            fct.append((n, 1))
        return fct
    def combinations_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        
        if n < 0 or r < 0:
            raise Exception('combinations_count(n, r) not defined when n or r is negative')
        if n - r < r: r = n - r
        if r < 0: return 0
        if r == 0: return 1
        if r == 1: return n
        numerator = [n - r + k + 1 for k in range(r)]
        denominator = [k + 1 for k in range(r)]
        for p in range(2,r+1):
            pivot = denominator[p - 1]
            if pivot > 1:
                offset = (n - r) % p
                for k in range(p-1,r,p):
                    numerator[k - offset] /= pivot
                    denominator[k] /= pivot
        result = 1
        for k in range(r):
            if numerator[k] > 1:
                result *= int(numerator[k])
        return result
    def combinations_with_replacement_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items allowing individual elements to be repeated more than once.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        if n < 0 or r < 0:
            raise Exception('combinations_with_replacement_count(n, r) not defined when n or r is negative')
        elif n == 0:
            return 1
        else:
            return combinations_count(n + r - 1, r)
    from bisect import bisect_left, bisect_right
    from collections import deque, Counter, defaultdict 
    from heapq import heapify, heappop, heappush, heappushpop, heapreplace,nlargest,nsmallest 
    from copy import deepcopy, copy 
    import operator
    from operator import itemgetter
    
    
    from functools import reduce, lru_cache
    def chmin(x, y):
        """change minimum
        if x > y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current minimum value
            y (long): potential minimum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x > y:
            x = y
            return (x, True)
        else:
            return (x, False)
    def chmax(x, y):
        """change maximum
        if x < y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current maximum value
            y (long): potential maximum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x < y:
            x = y
            return (x, True)
        else:
            return (x, False)

    from fractions import gcd 
    def gcds(numbers):
        return reduce(gcd, numbers)
    def lcm(x, y):
        return (x * y) // gcd(x, y)
    def lcms(numbers):
        return reduce(lcm, numbers, 1)

    
    
    INF = 10 ** 18
    MOD = 10 ** 9 + 7
    modpow = lambda a, n, p = MOD: pow(a, n, p) 
    def modinv(a, p = MOD):
        
        
        return modpow(a, p-2, p)
    def modinv_list(n, p = MOD):
        if n <= 1:
            return [0,1][:n+1]
        else:
            inv_t = [0,1]
            for i in range(2, n+1):
                inv_t += [inv_t[p % i] * (p - int(p / i)) % p]
            return inv_t
    def modfactorial_list(n, p = MOD):
        if n == 0:
            return [1]
        else:
            l = [0] * (n+1)
            tmp = 1
            for i in range(1, n+1):
                tmp = tmp * i % p
                l[i] = tmp
            return l
    def modcomb(n, k, fac_list = [], p = MOD):
        
        
        from math import factorial
        if n < 0 or k < 0 or n < k: return 0
        if n == 0 or k == 0: return 1
        if len(fac_list) <= n:
            a = factorial(n) % p
            b = factorial(k) % p
            c = factorial(n-k) % p
        else:
            a = fac_list[n]
            b = fac_list[k]
            c = fac_list[n-k]
        return (a * modpow(b, p-2, p) * modpow(c, p-2, p)) % p
    def modadd(a, b, p = MOD):
        return (a + b) % MOD
    def modsub(a, b, p = MOD):
        return (a - b) % p
    def modmul(a, b, p = MOD):
        return ((a % p) * (b % p)) % p
    def moddiv(a, b, p = MOD):
        return modmul(a, modpow(b, p-2, p))

    """ initialize variables and set inputs
    
        
        
    
        
        
        
        
        
    
        
        
        
        
    
        
        
    """

    
    r = lambda: sys.stdin.readline().strip()
    r_int = lambda: int(r())
    R = lambda: list(map(int, r().split()))
    Rmap = lambda: map(int, r().split())
    Rfloat = lambda: list(map(float, r().split()))
    Rtuple = lambda: tuple(map(int, r().split()))

    """ how to treat input
    
    
    
    
    
    
    
    """

    if __name__ != '__main__':
        
        sys.stdin = open('sample.txt')

    
    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    N, K = R()
    dp = [0]*2610*51*51
    ip = 2610*51
    restp = 2610
    dp[0] = 1
    for i in range(N):
        for rest in range(N):
            if rest > N //2:
                break
            for k in range(0, K+1, 2):                
                
                dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] += dp[i*ip+rest*restp+k]
                dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] %= MOD
                dp[(i+1)*ip+rest*restp+(k+2*rest)] += dp[i*ip+rest*restp+k] * (2*rest+1)
                dp[(i+1)*ip+rest*restp+(k+2*rest)] %= MOD
                if rest:
                    dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] += dp[i*ip+rest*restp+k] * rest * rest
                    dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] %= MOD
    print(dp[N*ip+K])
    
    
    

    """memo: how to use defaultdict of list
    
    Dic = defaultdict(list)
    
    Dic[x].append(y)
    
    for k, v in Dic.items():
    """

if __name__ == '__main__':
    main()

Solution (Python):
def main():

    """ convenient functions
    
    
    
    
    
    """

    """convenient decorator
    
    
        
        
        
        
        
        
        
        
        
        
    """
    
    
    import sys
    sys.setrecursionlimit(10**7)
    from itertools import accumulate, combinations, permutations, product 
    
    from math import factorial, ceil, floor, sqrt
    def factorize(n):
        """return the factors of the Arg and count of each factor
        
        Args:
            n (long): number to be resolved into factors
        
        Returns:
            list of tuples: factorize(220) returns [(2, 2), (5, 1), (11, 1)]
        """
        fct = []  
        b, e = 2, 0  
        while b * b <= n:
            while n % b == 0:
                n = n // b
                e = e + 1
            if e > 0:
                fct.append((b, e))
            b, e = b + 1, 0
        if n > 1:
            fct.append((n, 1))
        return fct
    def combinations_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        
        if n < 0 or r < 0:
            raise Exception('combinations_count(n, r) not defined when n or r is negative')
        if n - r < r: r = n - r
        if r < 0: return 0
        if r == 0: return 1
        if r == 1: return n
        numerator = [n - r + k + 1 for k in range(r)]
        denominator = [k + 1 for k in range(r)]
        for p in range(2,r+1):
            pivot = denominator[p - 1]
            if pivot > 1:
                offset = (n - r) % p
                for k in range(p-1,r,p):
                    numerator[k - offset] /= pivot
                    denominator[k] /= pivot
        result = 1
        for k in range(r):
            if numerator[k] > 1:
                result *= int(numerator[k])
        return result
    def combinations_with_replacement_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items allowing individual elements to be repeated more than once.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        if n < 0 or r < 0:
            raise Exception('combinations_with_replacement_count(n, r) not defined when n or r is negative')
        elif n == 0:
            return 1
        else:
            return combinations_count(n + r - 1, r)
    from bisect import bisect_left, bisect_right
    from collections import deque, Counter, defaultdict 
    from heapq import heapify, heappop, heappush, heappushpop, heapreplace,nlargest,nsmallest 
    from copy import deepcopy, copy 
    import operator
    from operator import itemgetter
    
    
    from functools import reduce, lru_cache
    def chmin(x, y):
        """change minimum
        if x > y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current minimum value
            y (long): potential minimum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x > y:
            x = y
            return (x, True)
        else:
            return (x, False)
    def chmax(x, y):
        """change maximum
        if x < y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current maximum value
            y (long): potential maximum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x < y:
            x = y
            return (x, True)
        else:
            return (x, False)

    from fractions import gcd 
    def gcds(numbers):
        return reduce(gcd, numbers)
    def lcm(x, y):
        return (x * y) // gcd(x, y)
    def lcms(numbers):
        return reduce(lcm, numbers, 1)

    
    
    INF = 10 ** 18
    MOD = 10 ** 9 + 7
    modpow = lambda a, n, p = MOD: pow(a, n, p) 
    def modinv(a, p = MOD):
        
        
        return modpow(a, p-2, p)
    def modinv_list(n, p = MOD):
        if n <= 1:
            return [0,1][:n+1]
        else:
            inv_t = [0,1]
            for i in range(2, n+1):
                inv_t += [inv_t[p % i] * (p - int(p / i)) % p]
            return inv_t
    def modfactorial_list(n, p = MOD):
        if n == 0:
            return [1]
        else:
            l = [0] * (n+1)
            tmp = 1
            for i in range(1, n+1):
                tmp = tmp * i % p
                l[i] = tmp
            return l
    def modcomb(n, k, fac_list = [], p = MOD):
        
        
        from math import factorial
        if n < 0 or k < 0 or n < k: return 0
        if n == 0 or k == 0: return 1
        if len(fac_list) <= n:
            a = factorial(n) % p
            b = factorial(k) % p
            c = factorial(n-k) % p
        else:
            a = fac_list[n]
            b = fac_list[k]
            c = fac_list[n-k]
        return (a * modpow(b, p-2, p) * modpow(c, p-2, p)) % p
    def modadd(a, b, p = MOD):
        return (a + b) % MOD
    def modsub(a, b, p = MOD):
        return (a - b) % p
    def modmul(a, b, p = MOD):
        return ((a % p) * (b % p)) % p
    def moddiv(a, b, p = MOD):
        return modmul(a, modpow(b, p-2, p))

    """ initialize variables and set inputs
    
        
        
    
        
        
        
        
        
    
        
        
        
        
    
        
        
    """

    
    r = lambda: sys.stdin.readline().strip()
    r_int = lambda: int(r())
    R = lambda: list(map(int, r().split()))
    Rmap = lambda: map(int, r().split())
    Rfloat = lambda: list(map(float, r().split()))
    Rtuple = lambda: tuple(map(int, r().split()))

    """ how to treat input
    
    
    
    
    
    
    
    """

    if __name__ != '__main__':
        
        sys.stdin = open('sample.txt')

    
    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    N, K = R()
    dp = [0]*2610*51*51
    ip = 2610*51
    restp = 2610
    dp[0] = 1
    for i, rest, k in product(range(N), range(N), range(0,K+1,2)):
        dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] += dp[i*ip+rest*restp+k]
        dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] %= MOD
        dp[(i+1)*ip+rest*restp+(k+2*rest)] += dp[i*ip+rest*restp+k] * (2*rest+1)
        dp[(i+1)*ip+rest*restp+(k+2*rest)] %= MOD
        if rest:
            dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] += dp[i*ip+rest*restp+k] * rest * rest
            dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] %= MOD
    print(dp[N*ip+K])
    
    
    

    """memo: how to use defaultdict of list
    
    Dic = defaultdict(list)
    
    Dic[x].append(y)
    
    for k, v in Dic.items():
    """

if __name__ == '__main__':
    main()

Solution (Python):
def main():

    """ convenient functions
    
    
    
    
    
    """

    """convenient decorator
    
    
        
        
        
        
        
        
        
        
        
        
    """
    
    
    import sys
    sys.setrecursionlimit(10**7)
    from itertools import accumulate, combinations, permutations, product 
    
    from math import factorial, ceil, floor, sqrt
    def factorize(n):
        """return the factors of the Arg and count of each factor
        
        Args:
            n (long): number to be resolved into factors
        
        Returns:
            list of tuples: factorize(220) returns [(2, 2), (5, 1), (11, 1)]
        """
        fct = []  
        b, e = 2, 0  
        while b * b <= n:
            while n % b == 0:
                n = n // b
                e = e + 1
            if e > 0:
                fct.append((b, e))
            b, e = b + 1, 0
        if n > 1:
            fct.append((n, 1))
        return fct
    def combinations_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        
        if n < 0 or r < 0:
            raise Exception('combinations_count(n, r) not defined when n or r is negative')
        if n - r < r: r = n - r
        if r < 0: return 0
        if r == 0: return 1
        if r == 1: return n
        numerator = [n - r + k + 1 for k in range(r)]
        denominator = [k + 1 for k in range(r)]
        for p in range(2,r+1):
            pivot = denominator[p - 1]
            if pivot > 1:
                offset = (n - r) % p
                for k in range(p-1,r,p):
                    numerator[k - offset] /= pivot
                    denominator[k] /= pivot
        result = 1
        for k in range(r):
            if numerator[k] > 1:
                result *= int(numerator[k])
        return result
    def combinations_with_replacement_count(n, r):
        """Return the number of selecting r pieces of items from n kinds of items allowing individual elements to be repeated more than once.
        
        Args:
            n (long): number
            r (long): number
        
        Raises:
            Exception: not defined when n or r is negative
        
        Returns:
            long: number
        """
        if n < 0 or r < 0:
            raise Exception('combinations_with_replacement_count(n, r) not defined when n or r is negative')
        elif n == 0:
            return 1
        else:
            return combinations_count(n + r - 1, r)
    from bisect import bisect_left, bisect_right
    from collections import deque, Counter, defaultdict 
    from heapq import heapify, heappop, heappush, heappushpop, heapreplace,nlargest,nsmallest 
    from copy import deepcopy, copy 
    import operator
    from operator import itemgetter
    
    
    from functools import reduce, lru_cache
    def chmin(x, y):
        """change minimum
        if x > y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current minimum value
            y (long): potential minimum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x > y:
            x = y
            return (x, True)
        else:
            return (x, False)
    def chmax(x, y):
        """change maximum
        if x < y, x = y and return (x, True).
        convenient when solving problems of dp[i]
        
        Args:
            x (long): current maximum value
            y (long): potential maximum value
        
        Returns:
            (x, bool): (x, True) when updated, else (x, False)
        """
        if x < y:
            x = y
            return (x, True)
        else:
            return (x, False)

    from fractions import gcd 
    def gcds(numbers):
        return reduce(gcd, numbers)
    def lcm(x, y):
        return (x * y) // gcd(x, y)
    def lcms(numbers):
        return reduce(lcm, numbers, 1)

    
    
    INF = 10 ** 18
    MOD = 10 ** 9 + 7
    modpow = lambda a, n, p = MOD: pow(a, n, p) 
    def modinv(a, p = MOD):
        
        
        return modpow(a, p-2, p)
    def modinv_list(n, p = MOD):
        if n <= 1:
            return [0,1][:n+1]
        else:
            inv_t = [0,1]
            for i in range(2, n+1):
                inv_t += [inv_t[p % i] * (p - int(p / i)) % p]
            return inv_t
    def modfactorial_list(n, p = MOD):
        if n == 0:
            return [1]
        else:
            l = [0] * (n+1)
            tmp = 1
            for i in range(1, n+1):
                tmp = tmp * i % p
                l[i] = tmp
            return l
    def modcomb(n, k, fac_list = [], p = MOD):
        
        
        from math import factorial
        if n < 0 or k < 0 or n < k: return 0
        if n == 0 or k == 0: return 1
        if len(fac_list) <= n:
            a = factorial(n) % p
            b = factorial(k) % p
            c = factorial(n-k) % p
        else:
            a = fac_list[n]
            b = fac_list[k]
            c = fac_list[n-k]
        return (a * modpow(b, p-2, p) * modpow(c, p-2, p)) % p
    def modadd(a, b, p = MOD):
        return (a + b) % MOD
    def modsub(a, b, p = MOD):
        return (a - b) % p
    def modmul(a, b, p = MOD):
        return ((a % p) * (b % p)) % p
    def moddiv(a, b, p = MOD):
        return modmul(a, modpow(b, p-2, p))

    """ initialize variables and set inputs
    
        
        
    
        
        
        
        
        
    
        
        
        
        
    
        
        
    """

    
    r = lambda: sys.stdin.readline().strip()
    r_int = lambda: int(r())
    R = lambda: list(map(int, r().split()))
    Rmap = lambda: map(int, r().split())
    Rfloat = lambda: list(map(float, r().split()))
    Rtuple = lambda: tuple(map(int, r().split()))

    """ how to treat input
    
    
    
    
    
    
    
    """

    if __name__ != '__main__':
        
        sys.stdin = open('sample.txt')

    
    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    N, K = R()
    dp = [0]*3100*51*51
    ip = 3100*51
    restp = 3100
    dp[0] = 1
    for i, rest, k in product(range(N), range(N), range(K+1)):
        if k % 2:
            continue
        dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] += dp[i*ip+rest*restp+k]
        dp[(i+1)*ip+(rest+1)*restp+(k+2*rest+2)] %= MOD

        dp[(i+1)*ip+rest*restp+(k+2*rest)] += dp[i*ip+rest*restp+k] * (2*rest+1)
        dp[(i+1)*ip+rest*restp+(k+2*rest)] %= MOD
        if rest:
            dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] += dp[i*ip+rest*restp+k] * rest * rest
            dp[(i+1)*ip+(rest-1)*restp+(k+2*rest-2)] %= MOD
    print(dp[N*ip+K])
    
    
    

    """memo: how to use defaultdict of list
    
    Dic = defaultdict(list)
    
    Dic[x].append(y)
    
    for k, v in Dic.items():
    """

if __name__ == '__main__':
    main()