This is the easy version of the problem. The only difference between the easy version and the hard version is the constraints on $$$n$$$. You can only make hacks if both versions are solved.A permutation of $$$1, 2, \ldots, n$$$ is a sequence of $$$n$$$ integers, where each integer from $$$1$$$ to $$$n$$$ appears exactly once. For example, $$$[2,3,1,4]$$$ is a permutation of $$$1, 2, 3, 4$$$, but $$$[1,4,2,2]$$$ isn't because $$$2$$$ appears twice in it.Recall that the number of inversions in a permutation $$$a_1, a_2, \ldots, a_n$$$ is the number of pairs of indices $$$(i, j)$$$ such that $$$i < j$$$ and $$$a_i > a_j$$$.Let $$$p$$$ and $$$q$$$ be two permutations of $$$1, 2, \ldots, n$$$. Find the number of permutation pairs $$$(p,q)$$$ that satisfy the following conditions:  $$$p$$$ is lexicographically smaller than $$$q$$$.  the number of inversions in $$$p$$$ is greater than the number of inversions in $$$q$$$. Print the number of such pairs modulo $$$mod$$$. Note that $$$mod$$$ may not be a prime.

The only line contains two integers $$$n$$$ and $$$mod$$$ ($$$1\le n\le 50$$$, $$$1\le mod\le 10^9$$$).

Print one integer, which is the answer modulo $$$mod$$$.

#include <bits/stdc++.h>

using namespace std;

#define ull unsigned long long
#define ll long long
#define ui unsigned int
#define us unsigned short
#define inf_int 1e9
#define inf_ll 1e18
#define smod 998244353

const int maxN = 55;

ll combin[maxN][maxN], fac[maxN];
ll table[2][maxN*maxN];
ll n, mod;

int main(){
	ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);

	cin >> n >> mod;

	fill(combin[0], combin[maxN], 0);
	fac[0] = 1;
	for(int x=0;x<maxN;x++){
		combin[x][0] = 1;
	}
	for(int x=1;x<maxN;x++){
		fac[x] = (x * 1ll * fac[x-1]) % mod;
		for(int y=1;y<=x;y++){
			combin[x][y] = (combin[x-1][y-1] + combin[x-1][y]) % mod;
		}
	}

	fill(table[0], table[2], 0);
	for(int x=0;x<maxN*maxN;x++) table[0][x] = 1;

	ll ans = 0;
	for(int x=1;x<=n;x++){
		for(int y=0;y<maxN*maxN;y++){
			ll val = 0;
			for(int z=1;z<=x;z++){
				if(z > 1 && y-z+1 >= 0){
					ans += (table[0][y-z+1] - (y-z+1 > 0 ? table[0][y-z] : 0) + mod) % mod * val % mod * combin[n][x] % mod * fac[n-x] % mod;
					ans %= mod;
				}

				val += table[0][maxN*maxN-1];
				if(val >= mod) val -= mod;
				if(y-z+1 >= 0) val -= table[0][y-z+1];
				if(val < 0) val += mod;
			}

			table[1][y] = table[0][y];
			if(y >= x) table[1][y] = (table[1][y] - table[0][y-x] + mod) % mod;

			if(y > 0) table[1][y] += table[1][y-1];
			table[1][y] %= mod;
		}
		swap(table[0], table[1]);
	}

	cout << ans << "\n";
    return 0;
}

#include<bits/stdc++.h>
#define PI 3.141592653589793238462
#define eps 1e-20
#define fi first
#define se second
using namespace std;
using cd = complex<double>;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<db,db> pdd;
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
//rnd()%n,shuffle(a+1,a+n+1,rnd);
ll n,mod,d[55][30000][3],ans,N=3000;
int main(){
    cin>>n>>mod;d[1][N][0]=1;
    for(ll i=1;i<n;i++){
        ll mx=(i*(i-1))/2,val=-2e18;
        for(ll j=-mx;j<=mx;j++){
            for(ll x=1;x<=i+1;x++){
                for(ll y=1;y<=i+1;y++){
                    if(x==y){
                        d[i+1][j+N][0]+=d[i][j+N][0];
                        d[i+1][j+N][1]+=d[i][j+N][1];
                        d[i+1][j+N][2]+=d[i][j+N][2];
                        d[i+1][j+N][0]%=mod;d[i+1][j+N][1]%=mod;d[i+1][j+N][2]%=mod;
                    }
                    else if(x<y){
                        d[i+1][j+x-y+N][1]+=d[i][j+N][0]+d[i][j+N][1]+d[i][j+N][2];
                        d[i+1][j+x-y+N][1]%=mod;
                    }
                    else{
                        d[i+1][j+x-y+N][2]+=d[i][j+N][0]+d[i][j+N][1]+d[i][j+N][2];
                        d[i+1][j+x-y+N][2]%=mod;
                    }
                }
            }
        }
    }
    for(ll i=1;i<=n*n;i++){
        ans+=d[n][i+N][1];ans%=mod;
    }
    cout<<ans<<endl;
}

#line 1 "codeforces-workspace\\contest\\1542\\e1\\e1.cpp"
// #undef _GLIBCXX_DEBUG
// #define NDEBUG
#include <bits/extc++.h>

#line 2 "Library\\lib\\alias"

/**
 * @file alias
 * @brief Alias
 */

#line 10 "Library\\lib\\alias"

#line 2 "Library\\lib\\bit"

#if __cplusplus > 201703L

#include <bit>

#elif __cplusplus > 201402L

#ifndef _GLIBCXX_BIT
#define _GLIBCXX_BIT 1

#include <limits>
#include <type_traits>

namespace std {

template <typename _Tp> constexpr int __countl_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) {
    constexpr int __diff = _Nd_u - _Nd;
    return __builtin_clz(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) {
    constexpr int __diff = _Nd_ul - _Nd;
    return __builtin_clzl(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) {
    constexpr int __diff = _Nd_ull - _Nd;
    return __builtin_clzll(__x) - __diff;
  } else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    unsigned long long __high = __x >> _Nd_ull;
    if (__high != 0) {
      constexpr int __diff = (2 * _Nd_ull) - _Nd;
      return __builtin_clzll(__high) - __diff;
    }
    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    return (_Nd - _Nd_ull) + __builtin_clzll(__low);
  }
}

template <typename _Tp> constexpr int __countr_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_ctz(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_ctzl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_ctzll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    if (__low != 0) return __builtin_ctzll(__low);
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_ctzll(__high) + _Nd_ull;
  }
}

template <typename _Tp> constexpr int __popcount(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return 0;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_popcount(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_popcountl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_popcountll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_popcountll(__low) + __builtin_popcountll(__high);
  }
}

template <typename _Tp> constexpr _Tp __bit_ceil(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0 || __x == 1) return 1;
  auto __shift_exponent = _Nd - __countl_zero((_Tp)(__x - 1u));
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
  if (!__builtin_is_constant_evaluated()) {
    __glibcxx_assert(__shift_exponent != numeric_limits<_Tp>::digits);
  }
#endif
  using __promoted_type = decltype(__x << 1);
  if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) {
    const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
    __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
  }
  return (_Tp)1u << __shift_exponent;
}

template <typename _Tp> constexpr _Tp __bit_floor(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0) return 0;
  return (_Tp)1u << (_Nd - __countl_zero((_Tp)(__x >> 1)));
}

template <typename _Tp> constexpr _Tp __bit_width(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  return _Nd - __countl_zero(__x);
}

}  // namespace std

#endif

#endif
#line 2 "Library\\lib\\limits"

#line 4 "Library\\lib\\limits"

namespace workspace {

template <class _Tp> struct numeric_limits : std::numeric_limits<_Tp> {};

#ifdef __SIZEOF_INT128__

template <> struct numeric_limits<__uint128_t> {
  constexpr static __uint128_t max() { return ~__uint128_t(0); }
  constexpr static __uint128_t min() { return 0; }
};

template <> struct numeric_limits<__int128_t> {
  constexpr static __int128_t max() {
    return numeric_limits<__uint128_t>::max() >> 1;
  }
  constexpr static __int128_t min() { return -max() - 1; }
};

#endif

}  // namespace workspace
#line 13 "Library\\lib\\alias"

namespace workspace {

constexpr static char eol = '\n';

using namespace std;

using i32 = int_least32_t;
using u32 = uint_least32_t;
using i64 = int_least64_t;
using u64 = uint_least64_t;

#ifdef __SIZEOF_INT128__
using i128 = __int128_t;
using u128 = __uint128_t;
#else
#warning 128-bit integer is not available.
#endif

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T2 &>() <
                              std::declval<const _T1 &>())>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y) noexcept {
  return __y < __x ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T2 &>(), std::declval<const _T1 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp min(std::initializer_list<_Tp> __x) noexcept {
  return *std::min_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp min(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::min_element(__x.begin(), __x.end(), __comp);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T1 &>() <
                              std::declval<const _T2 &>())>

constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y) noexcept {
  return __x < __y ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T1 &>(), std::declval<const _T2 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp max(std::initializer_list<_Tp> __x) noexcept {
  return *std::max_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp max(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::max_element(__x.begin(), __x.end(), __comp);
}

#ifdef _GLIBCXX_BIT

template <typename _Tp> constexpr _Tp __bsf(_Tp __x) noexcept {
  return std::__countr_zero(__x);
}

template <typename _Tp> constexpr _Tp __bsr(_Tp __x) noexcept {
  return std::__bit_width(__x) - 1;
}

#endif

}  // namespace workspace
#line 2 "Library\\lib\\cxx20"

/*
 * @file cxx20
 * @brief C++20 Features
 */

#line 9 "Library\\lib\\cxx20"

#if __cplusplus <= 201703L

#include <algorithm>
#include <vector>

namespace std {

/**
 * @brief Erase the elements of a container that do not satisfy the condition.
 * @param __cont Container.
 * @param __pred Predicate.
 * @return Number of the erased elements.
 */
template <typename _Tp, typename _Alloc, typename _Predicate>
inline typename vector<_Tp, _Alloc>::size_type erase_if(
    vector<_Tp, _Alloc>& __cont, _Predicate __pred) {
  const auto __osz = __cont.size();
  __cont.erase(remove_if(__cont.begin(), __cont.end(), __pred), __cont.end());
  return __osz - __cont.size();
}

/**
 * @brief Erase the elements of a container that are equal to the given value.
 * @param __cont Container.
 * @param __value Value.
 * @return Number of the erased elements.
 */
template <typename _Tp, typename _Alloc, typename _Up>
inline typename vector<_Tp, _Alloc>::size_type erase(
    vector<_Tp, _Alloc>& __cont, const _Up& __value) {
  const auto __osz = __cont.size();
  __cont.erase(remove(__cont.begin(), __cont.end(), __value), __cont.end());
  return __osz - __cont.size();
}

}  // namespace std

#endif
#line 1 "Library\\lib\\direct"
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#pragma GCC target("avx,avx2")
#pragma GCC optimize("unroll-loops")
#endif
#line 8 "codeforces-workspace\\contest\\1542\\e1\\e1.cpp"
// #include "lib/opt"
#line 2 "Library\\src\\sys\\call_once.hpp"

/**
 * @file call_once.hpp
 * @brief Call Once
 */

#line 9 "Library\\src\\sys\\call_once.hpp"

namespace workspace {

/**
 * @brief Call once.
 */
template <class _F> void call_once(_F &&__f) {
  static std::unordered_set<void *> __called;
  if (__called.count(std::addressof(__f))) return;
  __called.emplace(std::addressof(__f));
  __f();
}

}  // namespace workspace
#line 2 "Library\\src\\sys\\clock.hpp"

/**
 * @file clock.hpp
 * @brief Clock
 */

#line 9 "Library\\src\\sys\\clock.hpp"

namespace workspace {

using namespace std::chrono;

namespace internal {
// The start time of the program.
const auto start_time{system_clock::now()};
}  // namespace internal

/**
 * @return Elapsed time of the program.
 */
decltype(auto) elapsed() noexcept {
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - internal::start_time).count();
}

}  // namespace workspace
#line 2 "Library\\src\\sys\\ejection.hpp"

/**
 * @file ejection.hpp
 * @brief Ejection
 */

#line 9 "Library\\src\\sys\\ejection.hpp"

namespace workspace {

namespace internal {

struct ejection {
  bool exit = 0;
};

}  // namespace internal

/**
 * @brief eject from a try block, throw nullptr
 * @param arg output
 */
template <class Tp> void eject(Tp const &arg) {
  std::cout << arg << "\n";
  throw internal::ejection{};
}

void exit() { throw internal::ejection{true}; }

}  // namespace workspace
#line 2 "Library\\src\\sys\\iteration.hpp"

/**
 * @file iteration.hpp
 * @brief Case Iteration
 */

#line 9 "Library\\src\\sys\\iteration.hpp"

#line 11 "Library\\src\\sys\\iteration.hpp"

namespace workspace {

void main();

struct {
  // 1-indexed
  unsigned current{0};
  unsigned total{1};

  void read() { (std::cin >> total).ignore(); }

  int iterate() {
    static bool once = false;
    assert(!once);
    once = true;
    while (current++ < total) {
      try {
        main();
      } catch (internal::ejection const& status) {
        if (status.exit) break;
      }
    }
    return 0;
  }
} case_info;

}  // namespace workspace
#line 1 "Library\\lib\\utils"
// #include "src/utils/cached.hpp"
#line 2 "Library\\src\\utils\\cat.hpp"

/**
 * @file cat.hpp
 * @brief Cat
 */

#line 9 "Library\\src\\utils\\cat.hpp"

#line 2 "Library\\lib\\cxx17"

#ifndef _CXX17_CONSTEXPR
#if __cplusplus >= 201703L
#define _CXX17_CONSTEXPR constexpr
#else
#define _CXX17_CONSTEXPR
#endif
#endif

#if __cplusplus < 201703L

namespace std {

/**
 *  @brief  Return the size of a container.
 *  @param  __cont  Container.
 */
template <typename _Container>
constexpr auto size(const _Container& __cont) noexcept(noexcept(__cont.size()))
    -> decltype(__cont.size()) {
  return __cont.size();
}

/**
 *  @brief  Return the size of an array.
 */
template <typename _Tp, size_t _Nm>
constexpr size_t size(const _Tp (&)[_Nm]) noexcept {
  return _Nm;
}

}  // namespace std

#endif
#line 11 "Library\\src\\utils\\cat.hpp"

namespace workspace {

/**
 * @brief Concatenate two sequences.
 *
 * @param __c1
 * @param __c2
 * @return Concatenated sequence.
 */
template <class _C1, class _C2>
constexpr decltype(auto) cat(_C1 &&__c1, _C2 &&__c2) noexcept {
  auto __c = std::forward<_C1>(__c1);

  if _CXX17_CONSTEXPR (std::is_rvalue_reference<decltype(__c2)>::value)
    __c.insert(std::end(__c), std::make_move_iterator(std::begin(__c2)),
               std::make_move_iterator(std::end(__c2)));
  else
    __c.insert(std::end(__c), std::cbegin(__c2), std::cend(__c2));

  return __c;
}

/**
 * @return Concatenated sequence.
 */
template <class _C1, class _C2, class... _Args>
constexpr decltype(auto) cat(_C1 &&__c1, _C2 &&__c2,
                             _Args &&...__args) noexcept {
  return cat(cat(std::forward<_C1>(__c1), std::forward<_C2>(__c2)),
             std::forward<_Args>(__args)...);
}

}  // namespace workspace
#line 2 "Library\\src\\utils\\chval.hpp"

/**
 * @file chval.hpp
 * @brief Change Less/Greater
 */

#line 9 "Library\\src\\utils\\chval.hpp"

namespace workspace {

/**
 * @brief Substitute __y for __x if __y < __x.
 * @param __x Reference
 * @param __y Comparison target
 * @return Whether or not __x is updated.
 */
template <class _T1, class _T2,
          typename = decltype(std::declval<_T2>() < std::declval<_T1 &>())>
typename std::enable_if<std::is_assignable<_T1 &, _T2>::value, bool>::type chle(
    _T1 &__x, _T2 &&__y) noexcept {
  return __y < __x ? __x = std::forward<_T2>(__y), true : false;
}

/**
 * @brief Substitute __y for __x if __x < __y.
 * @param __x Reference
 * @param __y Comparison target
 * @return Whether or not __x is updated.
 */
template <class _T1, class _T2,
          typename = decltype(std::declval<_T1 &>() < std::declval<_T2>())>
typename std::enable_if<std::is_assignable<_T1 &, _T2>::value, bool>::type chgr(
    _T1 &__x, _T2 &&__y) noexcept {
  return __x < __y ? __x = std::forward<_T2>(__y), true : false;
}

/**
 * @brief Substitute __y for __x if __comp(__y, __x) is true.
 * @param __x Reference
 * @param __y Comparison target
 * @param __comp Compare function object
 * @return Whether or not __x is updated.
 */
template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(std::declval<_T2>(),
                                                       std::declval<_T1 &>()))>
typename std::enable_if<std::is_assignable<_T1 &, _T2>::value, bool>::type chle(
    _T1 &__x, _T2 &&__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __x = std::forward<_T2>(__y), true : false;
}

/**
 * @brief Substitute __y for __x if __comp(__x, __y) is true.
 * @param __x Reference
 * @param __y Comparison target
 * @param __comp Compare function object
 * @return Whether or not __x is updated.
 */
template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(std::declval<_T1 &>(),
                                                       std::declval<_T2>()))>
typename std::enable_if<std::is_assignable<_T1 &, _T2>::value, bool>::type chgr(
    _T1 &__x, _T2 &&__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __x = std::forward<_T2>(__y), true : false;
}

}  // namespace workspace
#line 1 "Library\\src\\utils\\compare.hpp"
/**
 * @file compare.hpp
 * @brief Compare
 */

#line 2 "Library\\src\\utils\\sfinae.hpp"

/**
 * @file sfinae.hpp
 * @brief SFINAE
 */

#line 10 "Library\\src\\utils\\sfinae.hpp"
#include <type_traits>

#ifndef __INT128_DEFINED__

#ifdef __SIZEOF_INT128__
#define __INT128_DEFINED__ 1
#else
#define __INT128_DEFINED__ 0
#endif

#endif

namespace std {

#if __INT128_DEFINED__

template <> struct make_signed<__uint128_t> { using type = __int128_t; };
template <> struct make_signed<__int128_t> { using type = __int128_t; };

template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };

template <> struct is_signed<__uint128_t> : std::false_type {};
template <> struct is_signed<__int128_t> : std::true_type {};

template <> struct is_unsigned<__uint128_t> : std::true_type {};
template <> struct is_unsigned<__int128_t> : std::false_type {};

#endif

}  // namespace std

namespace workspace {

template <class Tp, class... Args> struct variadic_front { using type = Tp; };

template <class... Args> struct variadic_back;

template <class Tp> struct variadic_back<Tp> { using type = Tp; };

template <class Tp, class... Args> struct variadic_back<Tp, Args...> {
  using type = typename variadic_back<Args...>::type;
};

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

/**
 * @brief Return type of subscripting ( @c [] ) access.
 */
template <class _Tp>
using subscripted_type =
    typename std::decay<decltype(std::declval<_Tp&>()[0])>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class _Tp, class = std::nullptr_t>
struct has_begin : std::false_type {};

template <class _Tp>
struct has_begin<_Tp, decltype(std::begin(std::declval<_Tp>()), nullptr)>
    : std::true_type {};

template <class _Tp, class = void> struct has_mod : std::false_type {};

template <class _Tp>
struct has_mod<_Tp, std::__void_t<decltype(_Tp::mod)>> : std::true_type {};

template <class _Tp, class = void> struct is_integral_ext : std::false_type {};
template <class _Tp>
struct is_integral_ext<
    _Tp, typename std::enable_if<std::is_integral<_Tp>::value>::type>
    : std::true_type {};

#if __INT128_DEFINED__

template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};

#endif

#if __cplusplus >= 201402

template <class _Tp>
constexpr static bool is_integral_ext_v = is_integral_ext<_Tp>::value;

#endif

template <typename _Tp, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename _Tp>
struct multiplicable_uint<
    _Tp,
    typename std::enable_if<(2 < sizeof(_Tp)) &&
                            (!__INT128_DEFINED__ || sizeof(_Tp) <= 4)>::type> {
  using type = uint_least64_t;
};

#if __INT128_DEFINED__

template <typename _Tp>
struct multiplicable_uint<_Tp,
                          typename std::enable_if<(4 < sizeof(_Tp))>::type> {
  using type = __uint128_t;
};

#endif

template <typename _Tp> struct multiplicable_int {
  using type =
      typename std::make_signed<typename multiplicable_uint<_Tp>::type>::type;
};

template <typename _Tp> struct multiplicable {
  using type = std::conditional_t<
      is_integral_ext<_Tp>::value,
      std::conditional_t<std::is_signed<_Tp>::value,
                         typename multiplicable_int<_Tp>::type,
                         typename multiplicable_uint<_Tp>::type>,
      _Tp>;
};

template <class> struct first_arg { using type = void; };

template <class _R, class _Tp, class... _Args>
struct first_arg<_R(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R (*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...) const> {
  using type = _Tp;
};

template <class _Tp, class = void> struct parse_compare : first_arg<_Tp> {};

template <class _Tp>
struct parse_compare<_Tp, std::__void_t<decltype(&_Tp::operator())>>
    : first_arg<decltype(&_Tp::operator())> {};

}  // namespace workspace
#line 7 "Library\\src\\utils\\compare.hpp"

#if __cplusplus >= 201703L

namespace workspace {

/**
 * @brief Compare 2 points by their value of `atan2`.
 *
 * @return
 */
template <class _Tp>
bool compare_arg(const _Tp& __p1, const _Tp& __p2) noexcept {
  const auto& [__x1, __y1] = __p1;
  const auto& [__x2, __y2] = __p2;

  using value_type = std::decay_t<decltype(__x1)>;
  using mul_type = typename multiplicable<value_type>::type;

  if (__y1 == value_type(0))
    return value_type(0) <= __x1 &&
           (value_type(0) < __y2 ||
            (__y2 == value_type(0) && __x2 < value_type(0)));

  return value_type(0) < __y1
             ? value_type(0) <= __y2 &&
                   mul_type(__y1) * __x2 < mul_type(__x1) * __y2
             : value_type(0) <= __y2 ||
                   mul_type(__y1) * __x2 < mul_type(__x1) * __y2;
}

}  // namespace workspace

#endif
#line 2 "Library\\src\\utils\\fixed_point.hpp"

/**
 * @file fixed_point.hpp
 * @brief Fixed Point Combinator
 */

#line 9 "Library\\src\\utils\\fixed_point.hpp"

namespace workspace {

/**
 * @brief Fixed Point Combinator.
 */
template <class _F> class fixed_point {
 public:
  // Construct a new fixed-point object.
  fixed_point(_F __x) noexcept : __fn(__x) {}

  // Function call.
  template <class... _Args> decltype(auto) operator()(_Args... __args) {
    return _wrapper{__fn}(std::forward<_Args>(__args)...);
  }

 private:
  _F __fn;

  struct _wrapper {
    _F &__ref;

    template <class... _Args> decltype(auto) operator()(_Args... __args) {
      return __ref(*this, std::forward<_Args>(__args)...);
    }
  };
};

}  // namespace workspace
#line 6 "Library\\lib\\utils"
// #include "src/utils/hash.hpp"
#line 2 "Library\\src\\utils\\io\\istream.hpp"

/**
 * @file istream.hpp
 * @brief Input Stream
 */

#include <cxxabi.h>

#line 13 "Library\\src\\utils\\io\\istream.hpp"

#line 16 "Library\\src\\utils\\io\\istream.hpp"

namespace workspace {

namespace _istream_impl {

template <class _Tp, typename = void> struct helper {
  helper(std::istream &__is, _Tp &__x) {
    if _CXX17_CONSTEXPR (has_begin<_Tp &>::value)
      for (auto &&__e : __x) helper<std::decay_t<decltype(__e)>>(__is, __e);
    else
      static_assert(has_begin<_Tp>::value, "istream unsupported type.");
  }
};

template <class _Tp>
struct helper<_Tp, std::__void_t<decltype(std::declval<std::istream &>() >>
                                          std::declval<_Tp &>())>> {
  helper(std::istream &__is, _Tp &__x) { __is >> __x; }
};

#ifdef __SIZEOF_INT128__

template <> struct helper<__uint128_t, void> {
  helper(std::istream &__is, __uint128_t &__x) {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') __neg = true, __s.erase(__s.begin());
    __x = 0;
    for (char __d : __s) {
      __x *= 10;
      __d -= '0';
      if (__neg)
        __x -= __d;
      else
        __x += __d;
    }
  }
};

template <> struct helper<__int128_t, void> {
  helper(std::istream &__is, __int128_t &__x) {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') __neg = true, __s.erase(__s.begin());
    __x = 0;
    for (char __d : __s) {
      __x *= 10;
      __d -= '0';
      if (__neg)
        __x -= __d;
      else
        __x += __d;
    }
  }
};

#endif  // INT128

template <class _T1, class _T2> struct helper<std::pair<_T1, _T2>> {
  helper(std::istream &__is, std::pair<_T1, _T2> &__x) {
    helper<_T1>(__is, __x.first), helper<_T2>(__is, __x.second);
  }
};

template <class... _Tp> struct helper<std::tuple<_Tp...>> {
  helper(std::istream &__is, std::tuple<_Tp...> &__x) { iterate(__is, __x); }

 private:
  template <class _Tuple, size_t _Nm = 0>
  void iterate(std::istream &__is, _Tuple &__x) {
    if _CXX17_CONSTEXPR (_Nm != std::tuple_size<_Tuple>::value) {
      helper<typename std::tuple_element<_Nm, _Tuple>::type>(
          __is, std::get<_Nm>(__x)),
          iterate<_Tuple, _Nm + 1>(__is, __x);
    }
  }
};

}  // namespace _istream_impl

/**
 * @brief A wrapper class for std::istream.
 */
class istream : public std::istream {
 public:
  /**
   * @brief Wrapped operator.
   */
  template <typename _Tp> istream &operator>>(_Tp &__x) {
    _istream_impl::helper<_Tp>(*this, __x);
    if (std::istream::fail()) {
      static auto once = atexit([] {
        std::cerr << "\n\033[43m\033[30mwarning: failed to read \'"
                  << abi::__cxa_demangle(typeid(_Tp).name(), 0, 0, 0)
                  << "\'.\033[0m\n\n";
      });
      assert(!once);
    }
    return *this;
  }
};

decltype(auto) cin = static_cast<istream &>(std::cin);

}  // namespace workspace
#line 8 "Library\\lib\\utils"
// #include "src/utils/io/ostream.hpp"
// #include "src/utils/io/read.hpp"
#line 2 "Library\\src\\utils\\grid\\motion.hpp"

/**
 * @file motion.hpp
 * @brief Motion
 */

#line 9 "Library\\src\\utils\\grid\\motion.hpp"

#line 11 "Library\\src\\utils\\grid\\motion.hpp"

namespace workspace {

/**
 * @brief Transpose.
 * @param __grid
 */
template <class _Grid,
          typename = decltype(std::declval<std::decay_t<_Grid>>()[0].resize(0))>
constexpr decltype(auto) transpose(_Grid &&__grid) noexcept {
#if __cplusplus < 201703L
  auto __h = __grid.size(), __w = __grid[0].size();
#else
  auto __h = std::size(__grid), __w = std::size(__grid[0]);
#endif
  std::decay_t<_Grid> __t(__w);
  for (auto &&__r : __t) __r.resize(__h);
  for (size_t __i = 0; __i != __h; ++__i)
    for (size_t __j = 0; __j != __w; ++__j)
      if _CXX17_CONSTEXPR (std::is_rvalue_reference<decltype(__grid)>::value)
        __t[__j][__i] = std::move(__grid[__i][__j]);
      else
        __t[__j][__i] = __grid[__i][__j];
  return __t;
}

/**
 * @brief Transpose.
 * @param __grid
 */
template <class _Tp, size_t _Rows, size_t _Cols>
constexpr decltype(auto) transpose(const _Tp (&__grid)[_Rows][_Cols]) noexcept {
  std::array<std::array<_Tp, _Rows>, _Cols> __t;
  for (size_t __i = 0; __i != _Rows; ++__i)
    for (size_t __j = 0; __j != _Cols; ++__j) __t[__j][__i] = __grid[__i][__j];
  return __t;
}

/**
 * @brief Transpose.
 * @param __grid
 */
template <class _Tp, size_t _Rows, size_t _Cols>
constexpr decltype(auto) transpose(_Tp(&&__grid)[_Rows][_Cols]) noexcept {
  std::array<std::array<_Tp, _Rows>, _Cols> __t;
  for (size_t __i = 0; __i != _Rows; ++__i)
    for (size_t __j = 0; __j != _Cols; ++__j)
      __t[__j][__i] = std::move(__grid[__i][__j]);
  return __t;
}

/**
 * @brief Transpose.
 * @param __grid
 */
template <class _Tp, size_t _Rows, size_t _Cols>
constexpr decltype(auto) transpose(
    const std::array<std::array<_Tp, _Cols>, _Rows> &__grid) noexcept {
  std::array<std::array<_Tp, _Rows>, _Cols> __t;
  for (size_t __i = 0; __i != _Rows; ++__i)
    for (size_t __j = 0; __j != _Cols; ++__j) __t[__j][__i] = __grid[__i][__j];
  return __t;
}

/**
 * @brief Transpose.
 * @param __grid
 */
template <class _Tp, size_t _Rows, size_t _Cols>
constexpr decltype(auto) transpose(
    std::array<std::array<_Tp, _Cols>, _Rows> &&__grid) noexcept {
  std::array<std::array<_Tp, _Rows>, _Cols> __t;
  for (size_t __i = 0; __i != _Rows; ++__i)
    for (size_t __j = 0; __j != _Cols; ++__j)
      __t[__j][__i] = std::move(__grid[__i][__j]);
  return __t;
}

/**
 * @brief Roll the grid counter-clockwise.
 * @param __grid
 */
template <class _Grid> decltype(auto) roll_ccw(_Grid &&__grid) noexcept {
  if _CXX17_CONSTEXPR (std::is_rvalue_reference<decltype(__grid)>::value) {
    auto __t = transpose(std::move(__grid));
    std::reverse(std::begin(__t), std::end(__t));
    return __t;
  } else {
    auto __t = transpose(__grid);
    std::reverse(std::begin(__t), std::end(__t));
    return __t;
  }
}

/**
 * @brief Roll the grid clockwise.
 * @param __grid
 */
template <class _Grid> decltype(auto) roll_cw(_Grid &&__grid) noexcept {
  if _CXX17_CONSTEXPR (std::is_rvalue_reference<decltype(__grid)>::value) {
    std::reverse(std::begin(__grid), std::end(__grid));
    return transpose(std::move(__grid));
  } else {
    auto __t = transpose(__grid);
    for (auto &&__r : __t) std::reverse(std::begin(__r), std::end(__r));
    return __t;
  }
}

}  // namespace workspace
#line 2 "Library\\src\\utils\\io\\setup.hpp"

/**
 * @file setup.hpp
 * @brief I/O Setup
 */

#line 10 "Library\\src\\utils\\io\\setup.hpp"

namespace workspace {

/**
 * @brief Setup I/O.
 * @param __n Standard output precision
 */
void io_setup(int __n) {
  std::cin.tie(0)->sync_with_stdio(0);
  std::cout << std::fixed << std::setprecision(__n);

#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (std::cin >> bufc)
      std::cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}

}  // namespace workspace
#line 2 "Library\\src\\utils\\iterator\\category.hpp"

/*
 * @file category.hpp
 * @brief Iterator Category
 */

#line 10 "Library\\src\\utils\\iterator\\category.hpp"

namespace workspace {

/*
 * @tparam Tuple Tuple of iterator types
 */
template <class Tuple, size_t N = std::tuple_size<Tuple>::value - 1>
struct common_iterator_category {
  using type = typename std::common_type<
      typename common_iterator_category<Tuple, N - 1>::type,
      typename std::iterator_traits<typename std::tuple_element<
          N, Tuple>::type>::iterator_category>::type;
};

template <class Tuple> struct common_iterator_category<Tuple, 0> {
  using type = typename std::iterator_traits<
      typename std::tuple_element<0, Tuple>::type>::iterator_category;
};

}  // namespace workspace
#line 2 "Library\\src\\utils\\iterator\\reverse.hpp"

/*
 * @file reverse_iterator.hpp
 * @brief Reverse Iterator
 */

#if __cplusplus >= 201703L

#include <iterator>
#include <optional>

namespace workspace {

/*
 * @class reverse_iterator
 * @brief Wrapper class for `std::reverse_iterator`.
 * @see http://gcc.gnu.org/PR51823
 */
template <class Iterator>
class reverse_iterator : public std::reverse_iterator<Iterator> {
  using base_std = std::reverse_iterator<Iterator>;
  std::optional<typename base_std::value_type> deref;

 public:
  using base_std::reverse_iterator;

  constexpr typename base_std::reference operator*() noexcept {
    if (!deref) {
      Iterator tmp = base_std::current;
      deref = *--tmp;
    }
    return deref.value();
  }

  constexpr reverse_iterator &operator++() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator &operator--() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator++(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator--(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
};

}  // namespace workspace

#endif
#line 14 "Library\\lib\\utils"
// #include "src/utils/make_vector.hpp"
// #include "src/utils/py-like/enumerate.hpp"
#line 2 "Library\\src\\utils\\py-like\\range.hpp"

/**
 * @file range.hpp
 * @brief Range
 */

#line 9 "Library\\src\\utils\\py-like\\range.hpp"

#line 2 "Library\\src\\utils\\py-like\\reversed.hpp"

/**
 * @file reversed.hpp
 * @brief Reversed
 */

#include <initializer_list>
#line 10 "Library\\src\\utils\\py-like\\reversed.hpp"

namespace workspace {

namespace _reversed_impl {

template <class _Container> class reversed {
  _Container __cont;

 public:
  constexpr reversed(_Container &&__cont) noexcept : __cont(__cont) {}

  constexpr decltype(auto) begin() noexcept { return std::rbegin(__cont); }
  constexpr decltype(auto) begin() const noexcept {
    return std::rbegin(__cont);
  }

  constexpr decltype(auto) end() noexcept { return std::rend(__cont); }
  constexpr decltype(auto) end() const noexcept { return std::rend(__cont); }

  constexpr decltype(auto) size() const noexcept {
    return
#if __cplusplus < 201703L
        __cont.size();
#else
        std::size(__cont);
#endif
  }
};

}  // namespace _reversed_impl

template <class _Container>
constexpr decltype(auto) reversed(_Container &&__cont) noexcept {
  return _reversed_impl::reversed<_Container>{std::forward<_Container>(__cont)};
}

template <class _Tp>
constexpr decltype(auto) reversed(
    std::initializer_list<_Tp> &&__cont) noexcept {
  return _reversed_impl::reversed<std::initializer_list<_Tp>>{
      std::forward<std::initializer_list<_Tp>>(__cont)};
}

}  // namespace workspace
#line 12 "Library\\src\\utils\\py-like\\range.hpp"

#if __cplusplus >= 201703L

namespace workspace {

template <class _Index> class range {
  _Index __first, __last;

 public:
  class iterator {
    _Index current;

   public:
    using difference_type = std::ptrdiff_t;
    using value_type = _Index;
    using reference = typename std::add_const<_Index>::type &;
    using pointer = iterator;
    using iterator_category = std::random_access_iterator_tag;

    constexpr iterator(const _Index &__i = _Index()) noexcept : current(__i) {}

    constexpr bool operator==(const iterator &__x) const noexcept {
      return current == __x.current;
    }
    constexpr bool operator!=(const iterator &__x) const noexcept {
      return current != __x.current;
    }

    constexpr bool operator<(const iterator &__x) const noexcept {
      return current < __x.current;
    }
    constexpr bool operator<=(const iterator &__x) const noexcept {
      return current <= __x.current;
    }

    constexpr bool operator>(const iterator &__x) const noexcept {
      return current > __x.current;
    }
    constexpr bool operator>=(const iterator &__x) const noexcept {
      return current >= __x.current;
    }

    constexpr iterator &operator++() noexcept {
      ++current;
      return *this;
    }
    constexpr iterator &operator++(int) noexcept {
      auto __tmp = *this;
      ++current;
      return __tmp;
    }

    constexpr iterator &operator--() noexcept {
      --current;
      return *this;
    }
    constexpr iterator &operator--(int) noexcept {
      auto __tmp = *this;
      --current;
      return __tmp;
    }

    constexpr difference_type operator-(const iterator &__x) const noexcept {
      return current - __x.current;
    }

    constexpr iterator &operator+=(difference_type __x) noexcept {
      current += __x;
      return *this;
    }
    constexpr iterator operator+(difference_type __x) const noexcept {
      return iterator(*this) += __x;
    }

    constexpr iterator &operator-=(difference_type __x) noexcept {
      current -= __x;
      return *this;
    }
    constexpr iterator operator-(difference_type __x) const noexcept {
      return iterator(*this) -= __x;
    }

    constexpr reference operator*() const noexcept { return current; }
  };

  template <class _Tp1, class _Tp2>
  constexpr range(const _Tp1 &__first, const _Tp2 &__last) noexcept
      : __first(__first), __last(__last) {}

  template <class _Tp>
  constexpr range(const _Tp &__last) noexcept : __first(), __last(__last) {}

  constexpr iterator begin() const noexcept { return iterator{__first}; }
  constexpr iterator end() const noexcept { return iterator{__last}; }

  constexpr reverse_iterator<iterator> rbegin() const noexcept {
    return reverse_iterator<iterator>(end());
  }
  constexpr reverse_iterator<iterator> rend() const noexcept {
    return reverse_iterator<iterator>(begin());
  }

  constexpr size_t size() const noexcept {
    return std::distance(__first, __last);
  }
};

template <class _Tp1, class _Tp2>
range(const _Tp1 &, const _Tp2 &)
    -> range<std::decay_t<decltype(++std::declval<_Tp1 &>())>>;

template <class _Tp>
range(const _Tp &) -> range<std::decay_t<decltype(++std::declval<_Tp &>())>>;

template <class... _Args>
constexpr decltype(auto) rrange(_Args &&...__args) noexcept {
  return reversed(range(std::forward<_Args>(__args)...));
}

template <class _Container>
constexpr decltype(auto) iterate(_Container &&__cont) noexcept {
  return range(std::begin(__cont), std::end(__cont));
}

template <class _Container>
constexpr decltype(auto) riterate(_Container &&__cont) noexcept {
  return range(std::rbegin(__cont), std::rend(__cont));
}

}  // namespace workspace

#endif
#line 18 "Library\\lib\\utils"
// #include "src/utils/py-like/zip.hpp"
#line 2 "Library\\src\\utils\\rand\\rng.hpp"

/**
 * @file rng.hpp
 * @brief Random Number Generator
 */

#line 9 "Library\\src\\utils\\rand\\rng.hpp"

namespace workspace {

template <typename _Arithmetic>
using uniform_distribution = typename std::conditional<
    std::is_integral<_Arithmetic>::value,
    std::uniform_int_distribution<_Arithmetic>,
    std::uniform_real_distribution<_Arithmetic>>::type;

template <typename _Arithmetic, class _Engine = std::mt19937>
class random_number_generator : uniform_distribution<_Arithmetic> {
  using base = uniform_distribution<_Arithmetic>;

  _Engine __engine;

 public:
  random_number_generator(_Arithmetic __min, _Arithmetic __max)
      : base(__min, __max), __engine(std::random_device{}()) {}

  random_number_generator(_Arithmetic __max = 1)
      : random_number_generator(0, __max) {}

  random_number_generator(typename base::param_type const& __param)
      : base(__param), __engine(std::random_device{}()) {}

  decltype(auto) operator()() noexcept { return base::operator()(__engine); }
};

}  // namespace workspace
#line 2 "Library\\src\\utils\\rand\\shuffle.hpp"

/**
 * @file shuffle.hpp
 * @brief Shuffle
 */

#line 10 "Library\\src\\utils\\rand\\shuffle.hpp"

namespace workspace {

template <class _RAIter, class _Engine = std::mt19937>
void shuffle(_RAIter __first, _RAIter __last) {
  static _Engine __engine(std::random_device{}());
  std::shuffle(__first, __last, __engine);
}

}  // namespace workspace
#line 2 "Library\\src\\utils\\round_div.hpp"

/*
 * @file round_div.hpp
 * @brief Round Integer Division
 */

#line 9 "Library\\src\\utils\\round_div.hpp"

#line 11 "Library\\src\\utils\\round_div.hpp"

namespace workspace {

/*
 * @fn floor_div
 * @brief floor of fraction.
 * @param x the numerator
 * @param y the denominator
 * @return maximum integer z s.t. z <= x / y
 * @note y must be nonzero.
 */
template <typename T1, typename T2>
constexpr typename std::enable_if<(is_integral_ext<T1>::value &&
                                   is_integral_ext<T2>::value),
                                  typename std::common_type<T1, T2>::type>::type
floor_div(T1 x, T2 y) {
  assert(y != 0);
  if (y < 0) x = -x, y = -y;
  return x < 0 ? (x - y + 1) / y : x / y;
}

/*
 * @fn ceil_div
 * @brief ceil of fraction.
 * @param x the numerator
 * @param y the denominator
 * @return minimum integer z s.t. z >= x / y
 * @note y must be nonzero.
 */
template <typename T1, typename T2>
constexpr typename std::enable_if<(is_integral_ext<T1>::value &&
                                   is_integral_ext<T2>::value),
                                  typename std::common_type<T1, T2>::type>::type
ceil_div(T1 x, T2 y) {
  assert(y != 0);
  if (y < 0) x = -x, y = -y;
  return x < 0 ? x / y : (x + y - 1) / y;
}

}  // namespace workspace
#line 22 "Library\\lib\\utils"
// #include "src\utils\rand\tree.hpp"
// #include "src\utils\reference_list.hpp"
#line 2 "Library\\src\\utils\\io\\input.hpp"

/**
 * @file input.hpp
 * @brief Input
 */

#line 9 "Library\\src\\utils\\io\\input.hpp"

namespace workspace {

namespace _input_impl {

template <class _Tp, bool _Is_class = false> class input {
  _Tp __value;

  template <class _Arg, class... _Args> struct is_same : std::false_type {};
  template <class _Arg> struct is_same<_Arg, _Arg> : std::true_type {};

 public:
  operator _Tp &() noexcept { return __value; }
  operator const _Tp &() const noexcept { return __value; }

  template <class... _Args>
  input(_Args &&...__args) noexcept : __value(std::forward<_Args>(__args)...) {
    if _CXX17_CONSTEXPR (!is_same<decltype(*this), _Args...>::value &&
                         !is_same<_Tp, _Args...>::value)
      cin >> __value;
  }

  input &operator=(const _Tp &__x) noexcept { return __value = __x, *this; }
};

template <class _Tp> class input<_Tp, true> : public _Tp {
  template <class _Arg, class... _Args> struct is_same : std::false_type {};
  template <class _Arg> struct is_same<_Arg, _Arg> : std::true_type {};

 public:
  operator _Tp &() noexcept { return *this; }
  operator const _Tp &() const noexcept { return *this; }

  template <class... _Args>
  input(_Args &&...__args) noexcept : _Tp(std::forward<_Args>(__args)...) {
    if _CXX17_CONSTEXPR (!is_same<decltype(*this), _Args...>::value &&
                         !is_same<_Tp, _Args...>::value)
      cin >> *this;
  }

  input &operator=(const _Tp &__x) noexcept {
    _Tp::operator=(__x);
    return *this;
  }
};

}  // namespace _input_impl

template <class _Tp>
using input = _input_impl::input<_Tp, std::is_class<_Tp>::value>;

}  // namespace workspace
#line 11 "codeforces-workspace\\contest\\1542\\e1\\e1.cpp"

// #include "lib/algebra"
// #include "lib/graph"
// #include "lib/modular"
// #include "lib/combinatorics"
// #include "lib/data_structure"
// #include "lib/number_theory"
// #include "lib/string"

signed main() {
  using namespace workspace;

  io_setup(15);

  /* given
    case_info.read();  //*/

  /* unspecified
    case_info.total = -1;  //*/

  return case_info.iterate();
}

#line 2 "Library\\src\\data_structure\\ndvec.hpp"

/**
 * @file ndvec.hpp
 * @brief Nd-vector
 */

#line 9 "Library\\src\\data_structure\\ndvec.hpp"

namespace workspace {

template <class _Tp, size_t _Nm>
class ndvec : public std::vector<ndvec<_Tp, _Nm - 1>> {
 public:
  static constexpr auto dimension = _Nm;
  using container_type = std::vector<ndvec<_Tp, _Nm - 1>>;

  template <class _Dim, size_t _Size>
  ndvec(const _Dim (&__dim)[_Size], const _Tp& __x = {})
      : container_type(__dim[_Size - _Nm], {__dim, __x}) {}
};

template <class _Tp> class ndvec<_Tp, 1> : public std::vector<_Tp> {
 public:
  static constexpr auto dimension = 1;
  using container_type = std::vector<_Tp>;

  template <class _Dim, size_t _Size>
  ndvec(const _Dim (&__dim)[_Size], const _Tp& __x = {})
      : container_type(__dim[_Size - 1], __x) {}
};

#if __cplusplus >= 201703L

template <class _Tp, class _Dim, size_t _Nm>
ndvec(const _Dim (&)[_Nm], const _Tp&) -> ndvec<_Tp, _Nm>;

#endif

}  // namespace workspace
#line 2 "Library\\src\\modular\\modint.hpp"

/**
 * @file modint.hpp
 *
 * @brief Modular Arithmetic
 */

#line 12 "Library\\src\\modular\\modint.hpp"

#line 2 "Library\\src\\number_theory\\sqrt_mod.hpp"

/**
 * @file sqrt_mod.hpp
 * @brief Tonelli-Shanks Algorithm
 */

#line 2 "Library\\src\\number_theory\\pow_mod.hpp"

/**
 * @file mod_pow.hpp
 * @brief Modular Exponentiation
 */

#line 9 "Library\\src\\number_theory\\pow_mod.hpp"

#line 11 "Library\\src\\number_theory\\pow_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular exponentiation.
 *
 * @param __x
 * @param __n Exponent
 * @param __mod Modulus
 * @return
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> pow_mod(
    _Tp __x, _Tp __n, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  mul_type __y{1};

  while (__n) {
    if (__n & 1) (__y *= __x) %= __mod;
    __x = (mul_type)__x * __x % __mod;
    __n >>= 1;
  }

  return __y;
};

}  // namespace workspace
#line 10 "Library\\src\\number_theory\\sqrt_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular square root.
 *
 * @param __x
 * @param __mod Modulus
 * @return One if it exists. Otherwise -1.
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> sqrt_mod(
    _Tp __x, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  if (!__x) return 0;

  if (__mod == 2) return __x;

  if (pow_mod(__x, __mod >> 1, __mod) != 1) return -1;

  _Tp __z = __builtin_ctz(__mod - 1), __q = __mod >> __z;

  mul_type __a = pow_mod(__x, (__q + 1) >> 1, __mod), __b = 2;
  while (pow_mod<_Tp>(__b, __mod >> 1, __mod) == 1) ++__b;
  __b = pow_mod<_Tp>(__b, __q, __mod);

  _Tp __shift = 0;

  for (auto __r = __a * __a % __mod * pow_mod(__x, __mod - 2, __mod) % __mod;
       __r != 1; (__r *= (__b *= __b) %= __mod) %= __mod) {
    auto __bsf = __z;

    for (auto __e = __r; __e != 1; --__bsf) (__e *= __e) %= __mod;

    while (++__shift != __bsf) (__b *= __b) %= __mod;

    (__a *= __b) %= __mod;
  }

  return __a;
};

}  // namespace workspace
#line 15 "Library\\src\\modular\\modint.hpp"

namespace workspace {

namespace _modint_impl {

template <auto _Mod, unsigned _Storage> struct modint {
  static_assert(is_integral_ext<decltype(_Mod)>::value,
                "_Mod must be integral type.");

  using mod_type = std::make_signed_t<typename std::conditional<
      0 < _Mod, std::add_const_t<decltype(_Mod)>, decltype(_Mod)>::type>;

  using value_type = std::decay_t<mod_type>;

  using mul_type = typename multiplicable_uint<value_type>::type;

  // Modulus
  static mod_type mod;

  static unsigned storage;

 private:
  value_type value = 0;

  struct direct_ctor_t {};
  constexpr static direct_ctor_t direct_ctor_tag{};

  // Direct constructor
  template <class _Tp>
  constexpr modint(_Tp __n, direct_ctor_t) noexcept : value(__n) {}

 public:
  constexpr modint() noexcept = default;

  template <class _Tp>
  constexpr modint(_Tp __n) noexcept
      : value((__n %= mod) < 0 ? __n + mod : __n) {}

  constexpr modint(bool __n) noexcept : value(__n) {}

  constexpr operator value_type() const noexcept { return value; }

  // unary operators {{
  constexpr modint operator++(int) noexcept {
    modint __t{*this};
    operator++();
    return __t;
  }

  constexpr modint operator--(int) noexcept {
    modint __t{*this};
    operator--();
    return __t;
  }

  constexpr modint &operator++() noexcept {
    if (++value == mod) value = 0;
    return *this;
  }

  constexpr modint &operator--() noexcept {
    if (!value)
      value = mod - 1;
    else
      --value;
    return *this;
  }

  constexpr modint operator+() const noexcept { return *this; }

  constexpr modint operator-() const noexcept {
    return {value ? mod - value : 0, direct_ctor_tag};
  }

  // }} unary operators

  // operator+= {{

  constexpr modint &operator+=(const modint &__x) noexcept {
    if ((value += __x.value) >= mod) value -= mod;
    return *this;
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> &operator+=(
      _Tp __x) noexcept {
    __x %= mod, value += __x;
    if (value < 0)
      value += mod;
    else if (value >= mod)
      value -= mod;
    return *this;
  }

  // }} operator+=

  // operator+ {{

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> operator+(
      _Tp const &__x) const noexcept {
    return modint{*this} += __x;
  }

  constexpr modint operator+(modint __x) const noexcept { return __x += *this; }

  template <class _Tp>
  constexpr friend std::enable_if_t<is_integral_ext<_Tp>::value, modint>
  operator+(_Tp const &__x, modint __y) noexcept {
    return __y += __x;
  }

  // }} operator+

  // operator-= {{

  constexpr modint &operator-=(const modint &__x) noexcept {
    if ((value -= __x.value) < 0) value += mod;
    return *this;
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> &operator-=(
      _Tp __x) noexcept {
    __x %= mod, value -= __x;
    if (value < 0)
      value += mod;
    else if (value >= mod)
      value -= mod;
    return *this;
  }

  // }} operator-=

  // operator- {{

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> operator-(
      _Tp const &__x) const noexcept {
    return modint{*this} -= __x;
  }

  constexpr modint operator-(const modint &__x) const noexcept {
    return modint{*this} -= __x;
  }

  template <class _Tp>
  constexpr friend std::enable_if_t<is_integral_ext<_Tp>::value, modint>
  operator-(_Tp __x, const modint &__y) noexcept {
    if (((__x -= __y.value) %= mod) < 0) __x += mod;
    return {__x, direct_ctor_tag};
  }

  // }} operator-

  // operator*= {{

  constexpr modint &operator*=(const modint &__x) noexcept {
    value =
        static_cast<value_type>(value * static_cast<mul_type>(__x.value) % mod);
    return *this;
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> &operator*=(
      _Tp __x) noexcept {
    value = static_cast<value_type>(
        value * mul_type((__x %= mod) < 0 ? __x + mod : __x) % mod);
    return *this;
  }

  // }} operator*=

  // operator* {{

  constexpr modint operator*(const modint &__x) const noexcept {
    return {static_cast<mul_type>(value) * __x.value % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> operator*(
      _Tp __x) const noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(value) * __x % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend std::enable_if_t<is_integral_ext<_Tp>::value, modint>
  operator*(_Tp __x, const modint &__y) noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(__x) * __y.value % mod, direct_ctor_tag};
  }

  // }} operator*

 protected:
  static value_type _mem(value_type __x) {
    static std::vector<value_type> __m{0, 1};
    static value_type __i = (__m.reserve(storage), 1);
    while (__i < __x) {
      ++__i;
      __m.emplace_back(mod - mul_type(mod / __i) * __m[mod % __i] % mod);
    }
    return __m[__x];
  }

  static value_type _div(mul_type __r, value_type __x) noexcept {
    assert(__x != value_type(0));
    if (!__r) return 0;

    std::make_signed_t<value_type> __v{};
    bool __neg = __x < 0 ? __x = -__x, true : false;

    if (static_cast<decltype(storage)>(__x) < storage)
      __v = _mem(__x);
    else {
      value_type __y{mod}, __u{1}, __t;

      while (__x)
        __t = __y / __x, __y ^= __x ^= (__y -= __t * __x) ^= __x,
        __v ^= __u ^= (__v -= __t * __u) ^= __u;

      if (__y < 0) __neg ^= 1;
    }

    if (__neg)
      __v = 0 < __v ? mod - __v : -__v;
    else if (__v < 0)
      __v += mod;

    return __r == mul_type(1) ? static_cast<value_type>(__v)
                              : static_cast<value_type>(__r * __v % mod);
  }

 public:
  // operator/= {{

  constexpr modint &operator/=(const modint &__x) noexcept {
    if (value) value = _div(value, __x.value);
    return *this;
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> &operator/=(
      _Tp __x) noexcept {
    if (value) value = _div(value, __x %= mod);
    return *this;
  }

  // }} operator/=

  // operator/ {{

  constexpr modint operator/(const modint &__x) const noexcept {
    if (!value) return {};
    return {_div(value, __x.value), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> operator/(
      _Tp __x) const noexcept {
    if (!value) return {};
    return {_div(value, __x %= mod), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend std::enable_if_t<is_integral_ext<_Tp>::value, modint>
  operator/(_Tp __x, const modint &__y) noexcept {
    if (!__x) return {};
    if ((__x %= mod) < 0) __x += mod;
    return {_div(__x, __y.value), direct_ctor_tag};
  }

  // }} operator/

  constexpr modint inv() const noexcept { return _div(1, value); }

  template <class _Tp>
  constexpr std::enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      _Tp __e) const noexcept {
    modint __r{mod != 1, direct_ctor_tag};

    for (modint __b{__e < 0 ? __e = -__e, _div(1, value) : value,
                              direct_ctor_tag};
         __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  template <class _Tp>
  constexpr friend std::enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      modint __b, _Tp __e) noexcept {
    if (__e < 0) {
      __e = -__e;
      __b.value = _div(1, __b.value);
    }

    modint __r{mod != 1, direct_ctor_tag};

    for (; __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  constexpr modint sqrt() const noexcept {
    return {sqrt_mod(value, mod), direct_ctor_tag};
  }

  friend constexpr modint sqrt(const modint &__x) noexcept {
    return {sqrt_mod(__x.value, mod), direct_ctor_tag};
  }

  friend std::istream &operator>>(std::istream &__is, modint &__x) noexcept {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') {
      __neg = true;
      __s.erase(__s.begin());
    }
    __x = 0;
    for (char __c : __s) __x = __x * 10 + (__c - '0');
    if (__neg) __x = -__x;
    return __is;
  }
};

template <auto _Mod, unsigned _Storage>
typename modint<_Mod, _Storage>::mod_type modint<_Mod, _Storage>::mod =
    _Mod > 0 ? _Mod : 0;

template <auto _Mod, unsigned _Storage>
unsigned modint<_Mod, _Storage>::storage = _Storage;

}  // namespace _modint_impl

template <auto _Mod, unsigned _Storage = 0,
          typename = std::enable_if_t<(_Mod > 0)>>
using modint = _modint_impl::modint<_Mod, _Storage>;

template <unsigned _Id = 0>
using modint_runtime = _modint_impl::modint<-(signed)_Id, 0>;

}  // namespace workspace
#line 36 "codeforces-workspace\\contest\\1542\\e1\\e1.cpp"

namespace workspace {

using mint = modint_runtime<>;
// using mint = int;

void main() {
  // start here!

  input<int> n;
  cin >> mint::mod;

  mint ans;
  vector<mint> dp(n * (n - 1) / 2 + 1);
  dp[0] = 1;

  ndvec bi({n + 1, n + 1}, mint());
  bi[0][0] = 1;
  for (auto i : range(n)) {
    for (auto j : range(i + 1)) {
      bi[i + 1][j] += bi[i][j];
      bi[i + 1][j + 1] += bi[i][j];
    }
  }

  for (auto i : range(n)) {
    // use dp

    auto dp2 = dp;  // suffix sum of dp
    partial_sum(rbegin(dp2), rend(dp2), rbegin(dp2));

    mint co, sum, sum2;
    for (auto s : range(i)) {
      if (s + 1 < dp2.size()) {
        sum += dp2[s + 1];
        sum2 += dp2[s + 1] * (i - s);
      }
    }

    for (auto s : range(dp.size())) {
      if (s + 1 < dp2.size()) sum -= dp2[s + 1];
      if (s + i + 1 < dp2.size()) sum += dp2[s + i + 1];
      if (s + 1 < dp2.size()) sum2 -= dp2[s + 1] * i;
      sum2 += sum;
      co += dp[s] * sum2;
    }

    for (auto j : range(i + 1, n)) {
      co *= j + 1;
    }
    ans += co;

    // update dp
    if (dp.size() > i) {
      for (auto j : rrange(dp.size() - i - 1)) {
        dp[j + i + 1] -= dp[j];
      }
    }
    partial_sum(begin(dp), end(dp), begin(dp));
  }

  cout << ans << "\n";
}

}  // namespace workspace

#include<bits/stdc++.h>
using namespace std;

long long f[100010],a[100010];
long long ret,md,mx,s;
int n;

int main()
{
	scanf("%d%lld",&n,&md);
	f[0]=1;
	for (int i=1;i<n;i++)
	{
		for (int j=mx;j>=0;j--)
			f[j+i]=(f[j+i]-f[j]+md)%md;
		for (int j=1;j<=mx+i;j++)
			f[j]=(f[j]+f[j-1]+md)%md;
		mx+=i-1;
		for (int j=1;j<=i;j++)
			a[j]=a[j-1]+i-j+1;
		s=0;
		for (int j=0;j<=mx;j++)
			for (int k=j+2;k<=mx;k++)
			{
				s=(s+f[j]*f[k]%md*a[min(i,k-j-1)])%md;
			}
		for(int j=i+2;j<=n;j++)
			s=s*j%md;
		ret=(ret+s+md)%md;
	}
	printf("%lld\n",ret);
	return 0;
}

#include<cstdio>
#include<set>
#include<algorithm>
#include<vector>
#include<stack>
#include<cmath>
#include<vector>
#include<cstring>
#include<queue>
#include<string>
#include<iostream>
#include<map>
#include<bitset>

#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=z;x>=y;x--)
#define LL long long

using namespace std;
const int N=505;
int n,mod,dp[N][N*N/2],s[N][N*N/2],ss[N*N/2],sss[N*N/2];

inline void init()
{
	dp[1][0]=s[1][0]=1;
	rep(j,1,(n-1)*n/2)
		s[1][j]=(dp[1][j]+s[1][j-1])%mod;
	rep(i,2,n)
	{
		rep(j,0,(i-1)*i/2)
		{
			int l=max(0,j-i+1);
			if(l) dp[i][j]=(dp[i][j]+((s[i-1][j]-s[i-1][l-1])%mod+mod)%mod)%mod;
			else dp[i][j]=(dp[i][j]+s[i-1][j])%mod;
		}
		s[i][0]=dp[i][0];
		rep(j,1,(n-1)*n/2)
			s[i][j]=(dp[i][j]+s[i][j-1])%mod;
	}
}

int main()
{
	scanf("%d%d",&n,&mod);
	init();
	int ans=0;
	rep(i,1,n)
	{
		int ti=n-i;
		sss[0]=s[i][0];
		rep(j,1,(ti-1)*ti/2)
			sss[j]=(s[ti][j]+sss[j-1])%mod;
		rep(j,1,(ti-1)*ti/2)
			ss[j]=(1ll*s[ti][j]*j%mod+ss[j-1])%mod;
		int c=1;
		per(j,ti+2,n)
			c=1ll*c*j%mod;
		int m=(ti-1)*(ti)/2,res=0;
		rep(y,0,m-1)
		{
			int temp=min(m-y,ti),l=ti+1-temp,r=ti;
			temp=(r-l+1)*(l+r)/2;
			res=(res+1ll*dp[ti][y]*s[ti][m]%mod*temp%mod)%mod;
		}
		rep(y,0,m-1)
		{
			int temp=min(m-y,ti),l=y,r=y+temp;
			temp=((ss[r]-ss[l])%mod+mod)%mod;
			int tem=1ll*(ti+y+1)*(((sss[r]-sss[l])%mod+mod)%mod)%mod;
			temp=((tem-temp)%mod+mod)%mod;
			res=((res-1ll*dp[ti][y]*temp%mod)%mod+mod)%mod;
		}
		ans=(ans+1ll*c*res%mod)%mod;
	}
	printf("%d",ans);
	return 0;
}

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 60
#define ll long long

int n,mo;
ll C[MAXN][MAXN],fac[MAXN];

ll f[MAXN][MAXN*MAXN],s1[MAXN][MAXN*MAXN],s2[MAXN][MAXN*MAXN];
ll g[MAXN][MAXN];
ll ans=0;
int lim[MAXN];

int main()
{
	scanf("%d%d",&n,&mo);
	C[0][0]=1;
	for(int i=1;i<=n;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo;
	}
	fac[0]=1;
	for(int i=1;i<=n;i++)
		fac[i]=fac[i-1]*i%mo;
//	int cur=0,pre=1;
	f[0][0]=1;
	s1[0][0]=s2[0][0]=1;
	for(int x=1;x<=n;x++){
		lim[x]=x*(x-1)/2;
		for(int j=0;j<=lim[x];j++){
			f[x][j]=s1[x-1][min(j,lim[x-1])];
			if(j>=x) f[x][j]=(f[x][j]-s1[x-1][min(j-x,lim[x-1])]+mo)%mo;
		}
		s2[x][0]=s1[x][0]=f[x][0];
		for(int j=1;j<=lim[x];j++){
			s1[x][j]=(s1[x][j-1]+f[x][j])%mo;
			s2[x][j]=(s2[x][j-1]+f[x][j])%mo;
		}
	}
//	for(int l=1;l<=n;l++){
//		ll now=0;
//		for(int x=1;x<=l;x++){
//			for(int y=x+1;y<=l;y++){
//				for(int i=y-x+1;i<=lim[l-1];i++)
//					now=(now+f[l-1][i]*s1[l-1][min(i+x-y-1,lim[l-1])]%mo)%mo;
//			}
//		}
//		ans=(ans+now*C[n][n-l]%mo*fac[n-l]%mo)%mo;
//	}
	for(int x=1;x<=n;x++){
		ll now=0;
		for(int i=2;i<=lim[x];i++){
			ll tmp=0;
			for(int d=2;d<=min(x,i);d++)
				tmp=(tmp+(x-d+1)*s1[x-1][min(i-d,lim[x-1])]%mo)%mo;
			now=(now+tmp*f[x-1][i]%mo)%mo;
		}
		ans=(ans+now*C[n][n-x]%mo*fac[n-x]%mo)%mo;
	}
	printf("%lld\n",ans);
	return 0;
}

#include<bits/stdc++.h>
#define ll long long
#define lll __int128
#define db double
#define ld long double
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
namespace IO
{
	const int SZ=1<<20;
	char gchar()
	{
	    static char buf[SZ];
	    static int i=SZ;
	    if(i==SZ)i=0,fread(buf,1,SZ,stdin);
	    return buf[i++];
	}
	void pchar(char c)
	{
	    static char buf[SZ];
	    static int i=0;
	    if(c)buf[i++]=c;
	    if(!c||i==SZ)fwrite(buf,1,i,stdout),i=0;
	}
	void pstr(string s,char end='\n')
	{
		for(char c:s)pchar(c);
		pchar(end);
	}
	template<typename T>void read(T &x)
	{
	    x=0;int f=1;
	    static char c;
	    while((c=gchar())>'9'||c<'0')if(c=='-')f=-1;
	    x=c-'0';
	    while((c=gchar())>='0'&&c<='9')
			x=(x<<1)+(x<<3)+(c^48);
		x*=f;
	}
	template<typename T,typename ...Args>void read(T &x,Args&...args){read(x),read(args...);}
	template<typename T>void i_write(T x)
	{
	    if(x>9)i_write(x/10);
	    pchar(x%10+'0');
	}
	template<typename T>void write(T x,char end='\n')
	{
	    if(x<0)pchar('-'),x=-x;
	    if(x>9)i_write(x/10);
	    pchar(x%10+'0');
	    pchar(end);
	}
}
using IO::read;
using IO::write;
const int N=510;
int n,mod,f[2][N*N],s[2][N*N],g[N*N],ans[N];
int main()
{
	scanf("%d%d",&n,&mod);
	s[0][0]=1,s[0][1]=-1;
	int m=n*(n-1)/2;
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=m;j++)s[(i&1)^1][j]=0;
		for(int j=0;j<=m;j++)
		{
			if(j)f[i&1][j]=(f[i&1][j-1]+s[i&1][j])%mod;
			else f[i&1][j]=s[i&1][j];
			s[(i&1)^1][j]=(s[(i&1)^1][j]+f[i&1][j])%mod;
			s[(i&1)^1][j+min(m-j,i)+1]=(s[(i&1)^1][j+min(m-j,i)+1]-f[i&1][j]+mod)%mod;
		}
		g[0]=f[i&1][0];
		for(int j=1;j<=i*(i-1)/2;j++)
			g[j]=(g[j-1]+f[i&1][j])%mod;
		for(int d=0;d<=i;d++)//q1-p1
			if(!d)ans[i+1]=(ans[i+1]+1ll*(i+1)*ans[i])%mod;
			else
			{
				for(int x=d+1;x<=i*(i-1)/2;x++)
					ans[i+1]=(ans[i+1]+1ll*(i-d+1)*f[i&1][x]%mod*g[x-d-1])%mod;
			}
	}
	printf("%d",ans[n]);
	IO::pchar(0);
	return 0;
}

/*
わんわん……わんだほーいっ☆
Wonderhoy!
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double DB;
char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<18,stdin),p1==p2)?EOF:*p1++)
int read()
{
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9')	c=getchar();
	while(c>='0' && c<='9')	x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
	return x;
}
void write(int x)
{
	if(x>9)	write(x/10);
	putchar(x%10+'0');
}
int MOD=998244353;
inline int Add(int u,int v){return u+v>=MOD?u+v-MOD:u+v;}
inline int Sub(int u,int v){return u-v>=0?u-v:u-v+MOD;}
inline int Mul(int u,int v){return LL(u)*LL(v)%MOD;}
inline int add(int &u,int v){return u=Add(u,v);}
inline int sub(int &u,int v){return u=Sub(u,v);}
inline int mul(int &u,int v){return u=Mul(u,v);}
int QuickPow(int x,int p=MOD-2)
{
	int ans=1,base=x;
	while(p)
	{
		if(p&1)	mul(ans,base);
		mul(base,base);
		p>>=1;
	}
	return ans;
}
int C[505][505],fac[505];
int n;
int f[250005],pre[250005],suf[250005],emu[500005];
int *g=emu+250000;
int main(){
	n=read(),MOD=read();
	C[0][0]=fac[0]=1;
	for(int i=1;i<=n;++i)	fac[i]=Mul(fac[i-1],i);
	for(int i=1;i<=n;++i)
	{
		C[i][0]=1;
		for(int j=1;j<=n;++j)	C[i][j]=Add(C[i-1][j-1],C[i-1][j]);
	}
	int ans=0;
	f[0]=1;
	for(int i=2;i<=n;++i)
	{
		int u=(i-1)*(i-2)/2,v=i*(i-1)/2;
		pre[0]=f[0];
		for(int d=1;d<=u;++d)	pre[d]=Add(pre[d-1],f[d]);
		suf[u]=f[u];
		for(int d=u-1;~d;--d)	suf[d]=Add(suf[d+1],f[d]);
		g[u]=suf[u];
		for(int d=u-1;d>=-i;--d)	g[d]=Add(g[d+1],suf[max(d,0)]);
		int w=0,c=0;
		for(int d=0;d<=u;++d)
		{
			add(w,Mul(f[d],Sub(c,Mul(i,d==0?0:pre[d-1]))));
			add(c,Sub(g[d-i+1],Add(g[d+1],Mul(i,suf[d+1]))));
		}
		add(ans,Mul(w,Mul(C[n][n-i],fac[n-i])));
		for(int d=0;d<=v;++d)
		{
			int l=d-(i-1),r=min(u,d);
			if(l<=0)	f[d]=pre[r];
			else if(l<=r)	f[d]=Sub(pre[r],pre[l-1]);
		}
	}
	write(ans),puts("");
	return 0;
}

#include "bits/stdc++.h"

using namespace std;

const int N = 55;

unsigned long long mod;
unsigned long long F[N];
unsigned long long dp[N][N*N];
unsigned long long DP[N][N*N];
unsigned long long C[N][N];

unsigned long long memo(int n, int d) {
    int m = n * (n - 1) / 2;
    if(d > m) return 0;
    if(DP[n][d] != -1) return DP[n][d];
    unsigned long long ans = memo(n, d+1);
    for(int i=m; i>=d; i--) {
        ans = (ans + (dp[n][i] * dp[n][i-d]) % mod) % mod;
    }
    return DP[n][d] = ans;
}

unsigned long long get(int n) {
    unsigned long long ans = 0;
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {
            int diff = j - i + 1;
            ans = (ans + memo(n-1, diff)) % mod;
        }
    }
    return ans;
}

void init() {
    memset(DP, -1, sizeof DP);
    memset(dp, 0, sizeof dp);
    dp[1][0] = 1;
    for(int i=2; i<N; i++) {
        for(int j=0; j<=i*(i-1)/2; j++) {
            for(int k=1; k<=i && j - k + 1 >= 0; k++) {
                dp[i][j] = (dp[i][j] + dp[i - 1][j - k + 1]) ;
                dp[i][j] %= mod;
            }
        }
    }
}

unsigned long long cc(int n, int k) {
    if(k < 0 || k > n) return 0;
    if(k == 0 || k == n) return 1%mod;
    if(C[n][k] != -1) return C[n][k];
    return C[n][k] = (cc(n-1, k) + cc(n-1, k-1)) % mod;
}

void solve() {
    memset(C, -1, sizeof C);
    int n;
    cin >> n >> mod;
    init();
    F[0] = 1%mod;
    for(int i=1; i<N; i++) F[i] = (F[i-1] * i) % mod;
    unsigned long long ans = 0;
    for(int pre=0; pre<n-1; pre++) {
        unsigned long long pref = (F[pre] * cc(n, pre)) % mod;
        ans = (ans + (pref * get(n-pre)) % mod) % mod;
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int tc = 1;
    // cin >> tc;
    for(int qq = 1; qq <= tc; qq++) {
        // cout << "Case #" << i << ":";
        solve();
    }

    return 0;
}

#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
//#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
using namespace std;
using i64 = long long;
using i128 = __int128;
#define MAXN 1000005
#define MAXM 1000005
#define M 1000000
#define K 17
#define MAXP 25
#define MAXK 55
#define MAXC 255
#define MAXERR 105
#define MAXLEN 105
#define MDIR 10
#define MAXR 705
#define BASE 102240
#define MAXA 28
#define MAXT 100005
#define LIMIT 86400
#define MAXV 305
#define LEQ 1
#define EQ 0
#define OP 0
#define CLO 1
#define DIG 1
#define C1 0
#define C2 1
#define PLUS 0
#define MINUS 1
#define MUL 2
#define CLO 1
#define VERT 1
//#define B 31
#define B2 1007
#define W 1
#define H 19
#define SPEC 1
#define MUL 2
#define CNT 3
#define ITER 1000
#define INF 1e9
#define EPS 1e9
#define MOD 998244353
#define FACT 100000000000000
#define PI 3.14159265358979
#define SRC 0
typedef long long ll;
typedef ll hash_t;
typedef __int128_t lint;
typedef long double ld;
typedef pair<int,int> ii;
typedef pair<double,int> ip;
typedef pair<ll,ii> pl;
typedef pair<ll,ll> pll;
typedef pair<ll,int> li;
typedef pair<ll,ll> iv;
typedef tuple<ll,int,int> iii;
typedef vector<vector<int>> vv;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ii> vii;
typedef vector<vector<ll>> vll;
typedef complex<ld> cd;
#define pb push_back
#define eb emplace_back
#define ins insert
#define er erase
#define sc second
#define fr first
#define repl(i,x,y) for (int i = (x); i <= (y); ++i)
#define rep(i,x,y) for (int i = (x); i < (y); ++i)
#define rev(i,x,y) for (int i = (x); i >= (y); --i)
#define LSOne(S) (S & (-S))
#define trav(i,v) for (auto &i : v)
#define foreach(it,v) for (auto it = begin(v); it != end(v); ++it)
#define bend(v) (v).begin(), (v).end()
#define rbend(v) (v).rbegin(), (v).rend()
#define sortarr(v) sort(bend(v))
#define rsortarr(v) sort(rbend(v))
#define unique(v) v.erase(unique(v.begin(), v.end()), v.end())
#define combine(A,B) A.insert(end(A), bend(B))
template<class T> bool ckmin(T &a, T &b) {return a > b ? a = b, 1 : 0; };
template<class T> bool ckmax(T &a, T &b) {return a < b ? a = b, 1 : 0; };
template<class T> void amax(T &a, T b, T c) { a = max(b, c); };
template<class T> void amin(T &a, T b, T c) { a = min(b, c); };
template<class T> T getmax(vector<T> &v) { return *max_element(bend(v)); };
template<class T> T getmin(vector<T> &v) { return *min_element(bend(v)); };
template<class T> int compress(vector<T> &v, T &val) { return (int)(lower_bound(bend(v), val) - begin(v)); };
template<class T> auto vfind(vector<T> &v, T &val) {
    return find(bend(v), val);
}
template<class T> auto verase(vector<T> &v, T &val) {
    return v.er(vfind(v, val));
}

int n,m;
//use offset trick to handle negative indices
const int B = 13005;
//ans(i) stores the number of pairs of permuations of length i where permutation p is lexicographically smaller than permutation q
ll dp[3][2 * B + 5], s[3][2 * B + 5], ans[2 * B + 5];
//we can see that problem boils down to inserting elements in increasing order
//state is(current number of elements inserted, number of inversions formed)

//state can be optimised to (current number of elements inserted, difference of inversions between permutations p and q after i elements are inserted)

//when ith element is inserted at position I and position J, inversion increase in I will be i - I and inversion increase in J will be i - J, leading to a relative change of J - I with i - |J - I| pairs of integers that can add that specific delta

//we can see that dp(n, k + 1) = dp(n, k) - (s(n - 1, k) - s(n - 1, k - n)) + s(n - 1, k + n) - s(n - 1, k)

//to handle lexicographically smaller case we can use the trick of maintaning a mutually exclusive condition where the first element added in p is stricly smaller than in q, then build a DP, in this case the mutually exclusive condition is the first element, we maintain the invariant where p1 < q1 and add the contribtion of all cases where p1 = q1 to the final answer

int main() {
    cin >> n >> m;
    dp[0][B] = s[0][B] = 1;
    rep(i,B,2*B+1) s[0][i] = 1;
    rep(i,1,n+1) {
        ll curr = 1;
        int I = i & 1, J = I ^ 1;
        rep(j,0,2*B+5) dp[I][j] = s[I][j] = 0;
        int st = (i * (i - 1)) / 2; //number of inversions formed after i elements are inserted
        rep(j, -st + B, st + B + 1) {
            dp[I][j] = curr;
            curr = (curr - s[J][j] + 2LL * m) % m;
            curr = (curr + s[J][j - i]) % m;

            curr = (curr + s[J][j + i]) % m;
            curr = (curr - s[J][j] + 2LL * m) % m;
        }

        //prefix sum here
        st = B - (i * (i - 1)) / 2;
        rep(j, st, B + ((i + 2) * (i + 1)) / 2 + 1) s[I][j] = (s[I][j - 1] + dp[I][j]) % m;

        rep(j,1,i) { //brute force change in difference in inversions between p and q
            ll incr = (s[J][((i) * (i - 1)) / 2 + B] - s[J][j + B] + 2LL * m) % m;
            //i - j ways to select (p1, q1) where q1 - p1 = j and p1 < q1
            //so every element from s[J][((i) * (i - 1)) / 2 + B] - s[J][j + B] will be added (i - j) times by contribution sum
            incr = (incr * (i - j)) % m;
            ans[i] = (ans[i] + incr) % m;
        }
    }
    //there are i choices in order for p1 to equal to q1 and pk < qk for some k > 1
    rep(i,2,n+1) ans[i] = ((((i * ans[i - 1])) % m) + ans[i]) % m;
    cout << ans[n];
}

// LUOGU_RID: 94931124
#include <cstdio>
#include <map>
#include <iostream>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <bitset>
#include <queue>
#include <stack>
#include <random>
#include <cstring>
#include <ctime>
#include <cmath>
#include <assert.h>
using namespace std;
#define LL long long
#define pp pair<int,int>
#define mp make_pair
#define ull unsigned long long
namespace IO{
    const int sz=1<<22;
    char a[sz+5],b[sz+5],*p1=a,*p2=a,*t=b,p[105];
    inline char gc(){
		return getchar();
    //    return p1==p2?(p2=(p1=a)+fread(a,1,sz,stdin),p1==p2?EOF:*p1++):*p1++;
    }
    template<class T> void gi(T& x){
        x=0; int f=1;char c=gc();
        if(c=='-')f=-1;
        for(;c<'0'||c>'9';c=gc())if(c=='-')f=-1;
        for(;c>='0'&&c<='9';c=gc())
            x=x*10+(c-'0');
        x=x*f;
    }
    inline void flush(){fwrite(b,1,t-b,stdout),t=b; }
    inline void pc(char x){*t++=x; if(t-b==sz) flush(); }
    template<class T> void pi(T x,char c='\n'){
        if(x<0)pc('-'),x=-x;
        if(x==0) pc('0'); int t=0;
        for(;x;x/=10) p[++t]=x%10+'0';
        for(;t;--t) pc(p[t]); pc(c);
    }
    struct F{~F(){flush();}}f;
}
using IO::gi;
using IO::pi;
using IO::pc;
int mod;
inline int add(int x,int y){
    return x+y>=mod?x+y-mod:x+y;
}
inline int dec(int x,int y){
    return x-y<0?x-y+mod:x-y;
}
inline int mul(int x,int y){
    return 1ll*x*y%mod;
}
inline int qkpow(int a,int b){
    if(b<0)return 0;
    int ans=1,base=a%mod;
    while(b){
        if(b&1)ans=1ll*ans*base%mod;
        base=1ll*base*base%mod;
        b>>=1;
    }
    return ans;
}
int n,ans,dp[505][125005],s1[125005],s2[125005],s3[125005],C[505][505],fac[505];
int S0(int l,int r){
	if(l>r)return 0;
	return dec(s1[r],(l?s1[l-1]:0));
}
int S1(int l,int r){
	if(l>r)return 0;
	return dec(s2[r],(l?s2[l-1]:0));
}
int S2(int l,int r){
	if(l>r)return 0;
	return dec(s3[r],(l?s3[l-1]:0));
}
signed main(){
	gi(n),gi(mod);
	for(int i=0;i<=125000;i++)s1[i]=1;
	dp[1][0]=1;
	for(int i=2;i<=n;i++){
		for(int j=0;j<=i*(i-1)/2;j++){
			dp[i][j]=s1[j];
			if(j>=i)
				dp[i][j]=dec(dp[i][j],s1[j-i]);
		}
		s1[0]=dp[i][0];
		for(int j=1;j<=125000;j++)
			s1[j]=add(s1[j-1],dp[i][j]);
	}
	C[0][0]=1;fac[0]=1;
	for(int i=1;i<=500;i++){
		C[i][0]=1;
		fac[i]=1ll*fac[i-1]*i%mod;
		for(int j=1;j<=i;j++)
			C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	}
	for(int i=0;i<n;i++){
		int lim=i*(i+1)/2,s=0;
		memset(s1,0,sizeof s1);
		memset(s2,0,sizeof s2);
		memset(s3,0,sizeof s3);
		s1[0]=dp[i][0];
		for(int j=1;j<=i*(i-1)/2;j++){
			s1[j]=add(s1[j-1],dp[i][j]);
			s2[j]=add(s2[j-1],1ll*j*dp[i][j]%mod);
			s3[j]=add(s3[j-1],1ll*j*(j+1)/2*dp[i][j]%mod);
		}
		for(int j=0;j<=i*(i-1)/2;j++){
			s=add(s,1ll*lim*s1[j-1]%mod*dp[i][j]%mod);
			int T=i+1-j;
			int A=1ll*T*(T+1)/2%mod;
			A=(A+mod)%mod;
			int xs=add(add(1ll*A*S0(max(0,j-i),j-1)%mod,1ll*(T%mod+mod)%mod*S1(max(0,j-i),j-1)%mod),S2(max(0,j-i),j-1));
			s=dec(s,1ll*xs*dp[i][j]%mod);
		}
		ans=add(ans,1ll*s*C[n][n-i-1]%mod*fac[n-i-1]%mod);
	}
	pi(ans,'\n');
	return 0;
}
/*

*/

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=55;
int n,mod,f[maxn][maxn*maxn],sum[maxn][maxn*maxn],C[maxn][maxn],fac[maxn];
signed main(){
    cin>>n>>mod;
    C[0][0]=1;
    for(int i=1;i<maxn;i++){
        C[i][0]=C[i][i]=1;
        for(int j=1;j<i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    fac[0]=1;
    for(int i=1;i<maxn;i++)fac[i]=fac[i-1]*i%mod;
    f[1][0]=1;
    for(int i=2;i<=n;i++){
        for(int j=0;j<=i*i;j++){
            for(int k=1;k<=i;k++)
                f[i][j]+=f[i-1][j-i+k],f[i][j]%=mod;
        }
    }
    for(int i=1;i<=n;i++){
        sum[i][0]=f[i][0];
        for(int j=1;j<=i*i;j++)
            sum[i][j]=sum[i][j-1]+f[i][j],sum[i][j]%=mod;
    }
    int ans=0;
    for(int k=1;k<n;k++){
        int fi=C[n][k-1]*fac[k-1]%mod,F=0,r=n-k,m=r*(r-1)/2;
        for(int d=1;d<=r;d++){
            for(int i=d+1;i<=m;i++)
                F+=(r-d+1)*f[r][i]%mod*sum[r][i-d-1]%mod,F%=mod;
        }
        ans+=fi*F%mod;
        ans%=mod;
    }
    printf("%lld\n",ans);
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#define N 57
typedef long long ll;
template<typename T> inline void read(T &x) {
	x = 0; char c = getchar(); bool flag = false;
	while (!isdigit(c)) { if (c == '-') flag=  true; c = getchar(); }
	while (isdigit(c)) x = x * 10 + (c ^ 48), c =getchar();
	if (flag)	x = -x;
}
using namespace std;
int P;
inline int Mod(int x) { return x >= P ? x - P : x; }
int n;
int g[2][N * N], gS[N * N];
int C[N][N], jie[N];
inline void init() {
	for (int i = 0; i <= n; ++i) {
		C[i][0] = 1;
		for (int j = 1; j <= i; ++j)
			C[i][j] = Mod(C[i - 1][j - 1] + C[i - 1][j]);
	}
	jie[0] = 1;
	for (int i = 1; i <= n; ++i) jie[i] = 1ll * jie[i - 1] * i % P;
}
int main() {
	read(n), read(P);
	if (P == 1) return puts("0"), 0;
	init();
	int nwt = 0;
	g[nwt][0] = 1;
	int res = 0;
	for (int i = 1; i <= n; ++i) {
		nwt ^= 1;
		memset(g[nwt], 0, sizeof(g[nwt]));
		for (int j = 0; j <= i * i; ++j) if (g[nwt ^ 1][j]) {
			for (int k = 0; k < i; ++k) {
				g[nwt][j + k] = Mod(g[nwt][j + k] + g[nwt ^ 1][j]);
			}
		}
		gS[0] = g[nwt ^ 1][0];
		for (int j = 1; j <= i * i; ++j) gS[j] = Mod(gS[j - 1] + g[nwt ^ 1][j]);
		int tmp = 0;
		for (int c = 1; c <= i; ++c) {//bug
			for (int d = c + 1; d <= i; ++d) {
				for (int j = d - c + 1; j <= i * i; ++j) if (g[nwt ^ 1][j]) {
					tmp = (tmp + 1ll * g[nwt ^ 1][j] * gS[j - (d - c) - 1]) % P;
				}
			}
		}
		res = (res + 1ll * C[n][i] * tmp % P * jie[n - i]) % P;//Bug
	}
	printf("%d\n", (res % P + P) % P);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int M;

int add(int a, int b) {
  a += b;
  if (a >= M) return a - M;
  if (a < 0) return a + M;
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

void addup(int &a, int b) {
  a = add(a, b);
}

int func(int a) {
  return a * (a - 1) / 2;
}

const int N = 50 + 7;
const int S = N * (N - 1) / 2 + 7;
int n, sol[N], dp[N][S];

int main() {
  //freopen ("input", "r", stdin);

  cin >> n >> M;

  dp[0][0] = 1 % M;
  for (int i = 1; i <= n; i++) {
    vector<int> ant;
    int extra = func(i + 1);
    for (int j = -extra; j <= extra; j++) {
      ant.push_back(dp[i - 1][abs(j)]);
    }
    for (int j = 0; j <= func(i); j++) {

      for (int dif = -(i - 1); dif <= (i - 1); dif++) {
        int cnt = 0;

        for (int a = 0; a <= i - 1; a++) {
          int b = a - dif;
          if (0 <= b && b <= i - 1) cnt++;
        }
        addup(dp[i][j], mul(cnt, ant[j + dif + extra]));
      }
    }
  }
  for (int l = 1; l <= n; l++) {
    for (int dif = 1; dif <= l; dif++) {
      int kek = 0;
      for (int j = (dif + 1); j < S; j++) {
        addup(kek, dp[l - 1][abs(j)]);
      }
      addup(sol[l], mul(l - dif, kek));
    }
  }
  int print = 0;
  for (int i = 1; i <= n; i++) {
    print = add(sol[i], mul(i, print));
  }
  cout << print << "\n";
  return 0;
}

//fast with bitset but not always efficient
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//
#include<bits/stdc++.h>
using namespace std;
int64_t mod,n;
vector<int64_t> fact(55);
int main (){
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n>>mod;
    fact[n+1]=1;
    for (int i=n;i>=0;i--) fact[i]=fact[i+1]*i%mod;
    vector<vector<int64_t>> dp(n+1,vector<int64_t> (n*(n+1)+5));
    dp[1][n*(n+1)/2]=1;
    for (int k=2;k<=n;k++){
        for (int ij=-k+1;ij<=k-1;ij++){
            if (ij>0){
                for (int r=n*(n+1)-ij;r>=0;r--)
                    (dp[k][r+ij]+=(k-ij)*dp[k-1][r])%=mod;
            }
            else {
                for (int r=-ij;r<=n*(n+1);r++)
                    (dp[k][r+ij]+=(k+ij)*dp[k-1][r])%=mod;
            }
        }
    }
    // for (int i=1;i<=4;i++){
    //      for (int j=-5;j<=5;j++) cout<<dp[i][n*(n+1)/2+j]<<" ";
    //          cout<<'\n';
    // }
    int64_t finalsol=0;
    for (int k=0;k<n;k++){
        for (int ij=-1;ij>-(n-k);ij--){
            int64_t tmp=0;
            //cout<<i<<" "<<j<<"!\n";
            for (int r=n*(n+1)/2;r<=n*(n+1);r++) {
                if (r+ij>n*(n+1)/2) {
                    (tmp+=dp[n-k-1][r]*fact[n-k+1]%mod*(n-k+ij)%mod)%=mod;
                    //cout<<r-n*(n+1)/2<<" "<<dp[n-k-1][r]<<'\n';
                }
            }
            finalsol=(finalsol+tmp)%mod;
        }
    }
    cout<<finalsol<<'\n';
}

#include <bits/stdc++.h>
#define N 200005
#define fi first
#define sc second

using namespace std;
typedef pair<int, int> II;

int length , mod;

int answer[N] , first_dif[N];
int dynamic[55][N];
int sums_dynamic[55][N];

void solve()
{
    int limit_int = length * (length - 1)/2;

    for(int i = 1; i <= length; i++){
        dynamic[i][0] = 1;
        for(int j =1 , lim = i * (i-1)/2 ;j <= lim; j++){

            for(int fir = 1 , fir_lim = min( i , j+1 ) ; fir <= fir_lim ; fir++)
                dynamic[i][j] = ( dynamic[i][j] +  dynamic[i-1][j - ( fir - 1 ) ] ) % mod;
        }
    }

    for(int i =1 ;i <= length; i++){
        sums_dynamic[i][0] = 1;
        for(int j = 1, lim = i * (i-1)/2; j <= lim; j++)
            sums_dynamic[i][j] = ( sums_dynamic[i][j-1] + dynamic[i][j] ) % mod;
    }

    for(int i = 2;i <= length; i++){

        for(int fir = 1; fir < i; fir++)
        for(int sec = fir +1 ; sec <= i ; sec++)
            for(int total_int = 0, cur_lim = i * (i-1)/2 ; total_int <= cur_lim; total_int++){

                if( total_int - fir + 1 >= 0 )
                if( total_int - sec >= 0 )
                first_dif[i] = ( first_dif[i] + (long long)dynamic[i-1][total_int - fir + 1 ] * sums_dynamic[i-1][ total_int - sec ] )%mod;
            }
    }

    for(int i =1 ;i <= length; i++)
        answer[i] = ( (long long)i * answer[i-1] + first_dif[i] ) % mod;

    printf("%d", answer[length] );
}

int main()
{
    // freopen("main.inp", "r", stdin );

    scanf("%d %d", &length , &mod );
    solve();
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define sz(x) ((int)(x).size())

// #define MULTIPLE_CASES

ll n, MOD;

vector<vector<ll>> dp;

void solve()
{
    cin >> n >> MOD;
    dp.assign(n+1, vector<ll>(n*n));
    vector<vector<ll>> pref(n+1, vector<ll>(n*n));
    dp[0][0] = 1;
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 0; j <= i*(i-1)/2; ++j)
        {
            for(int k = 0; k < i && k <= j; ++k)
            {
                dp[i][j] = (dp[i][j] + dp[i-1][j-k]) % MOD;
            }
            // cout << i << " " << j << " " << dp[i][j] << "\n";
            pref[i][j+1] = (pref[i][j] + dp[i][j]) % MOD;
        }
    }

    vector<vector<ll>> fac(n+1, vector<ll>(n+1));
    for(ll i = 0; i <= n; ++i)
    {
        fac[i][i] = i;
        for(ll j = i-1; j > 0; --j)
        {
            fac[i][j] = (fac[i][j+1] * j) % MOD;
        }
    }
    ll ans = 0;
    for(int i = 1; i < n; ++i)
    {
        for(int j = 1; j <= n-i; ++j)
        {
            int k = n-i;
            for(int x = j+1; x <= k*(k-1)/2; ++x)
            {
                // ll p = (pref[k][k*(k-1)/2+1] - pref[k][x] + MOD) % MOD;
                ll p = dp[k][x];
                ll q = pref[k][x-j];
                ll add = k+1 - j;
                if(i > 1) add = (add * fac[n][k+2]) % MOD;
                add = (((add * p) % MOD) * q) % MOD;
                // cout << i << " " << j << " " << x << " " << add << "\n";
                ans = (ans + add) % MOD;
            }
        }
    }

    cout << ans << "\n";
}

int main()
{
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    #ifdef MULTIPLE_CASES
    int t;
    cin >> t;
    for(int i = 0; i < t; ++i)
    {
        solve();
    }
    #else
    solve();
    #endif
}

#include <bits/stdc++.h>

#define fr(i, a, b) for(int i = (a); i <= (b); i++)
#define rf(i, a, b) for(int i = (a); i >= (b); i--)
#define fe(x, y) for(auto& x : y)

#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple

#define pw(x) (1LL << (x))
#define sqr(x) (1LL * (x) * (x))
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template<typename T>
using ve = vector<T>;

#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
template<typename T>
using oset = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define fbo find_by_order
#define ook order_of_key

mt19937_64 rng(chrono::system_clock::now().time_since_epoch().count());

template<typename T>
bool umn(T& a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T>
bool umx(T& a, T b) { return a < b ? a = b, 1 : 0; }

const int N = 55;

int n, MOD;

int add(int a, int b) {
    a += b;
    if(a >= MOD) return a - MOD;
    return a;
}

void add_self(int& a, int b) {
    a = add(a, b);
}

int mult(int a, int b) {
    return 1LL * a * b % MOD;
}

int _dp[N][N * N * 2 + 1];
int& dp(int n, int k) {
    return _dp[n][k + N * N];
}

int M;
int t[N];
int ans[N];

int main() {
#ifndef LOCAL
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
#else
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
#endif

    cin >> n >> MOD;

    M = n * (n - 1) / 2;

    dp(1, 0) = 1;
    fr(i, 2, n) {
        fr(was, -M, M) {

            fr(inc, -(i - 1), i - 1) {
                // pos2 - pos1 = inc
                // 0 <= pos1, pos2 <= i - 1
                add_self(dp(i, was + inc), mult(dp(i - 1, was), (i - abs(inc)) % MOD));
            }

            // fr(pos1, 0, i - 1) {
            //     fr(pos2, 0, i - 1) {
            //         add_self(dp(i, was + pos2 - pos1), dp(i - 1, was));
            //     }
            // }
        }
    }

    fr(len, 1, n) {
        int sum = 0;

        fr(i, len, M) add_self(sum, dp(len - 1, i));

        rf(delta, len - 1, 1) {
            int ways = (len - delta) % MOD;
            add_self(t[len], mult(ways, sum));

            sum = add(sum, dp(len - 1, delta));
        }

        // fr(p1, 1, len) {
        //     fr(q1, p1 + 1, len) {
        //         // delta > q1 - p1

        //         fr(delta, q1 - p1 + 1, M) {
        //             add_self(t[len], dp(len - 1, delta));
        //         }
        //     }
        // }
    }

    fr(i, 1, n) {
        // cout << t[i] << " ";
        ans[i] = add(mult(ans[i - 1], i), t[i]);
    }
    // cout << "\n";

    cout << ans[n] << "\n";

    return 0;
}

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define int long long
#define N 400000
using namespace std;
int n,mod,f[2][N+5],pre[2][N+5],ans[N];
signed main() {
	cin>>n>>mod;
	f[0][N>>1]=pre[0][N>>1]=1;
	for(int i=N>>1;i<=N;i++)pre[0][i]=1;
	for(int i=1;i<=n;i++){
		int now=i&1,sum=1;
		memset(f[now],0,sizeof(f[now]));
		memset(pre[now],0,sizeof(pre[now]));
		for(int j=200000-i*(i-1)/2;j<=200000+i*(i-1)/2;j++){
			f[now][j]=sum;
			sum=(sum-pre[now^1][j]*2+pre[now^1][j-i]+pre[now^1][j+i]+mod+mod)%mod;
		}
		for(int j=200000-i*(i-1)/2;j<=200000+(i+1)*(i+2)/2;j++)pre[now][j]=(pre[now][j-1]+f[now][j])%mod;
		for(int j=1;j<i;j++) ans[i]=(ans[i]+(pre[now^1][i*(i+1)/2+200000]-pre[now^1][200000+j]+mod)*(i-j))%mod;
	}

	for(int i=2;i<=n;i++)ans[i]=(ans[i-1]*i+ans[i])%mod;
	cout<<ans[n]<<endl;
}
//aaaaa
//ababa
//aabaa
//ababa
//aaaaa
//
//
//
//
//

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,mod,f[N][N*N+N],C[N][N],jie[N];
void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>mod;
	f[1][0]=1;
	for(int i=1;i<=n;i++){
		if(i!=1)for(int j=1;j<=i*(i-1)/2+1;j++)add(f[i][j],f[i][j-1]);
//		for(int j=0;j<=10;j++)cout<<f[i][j]<<' ';
		for(int j=0;j<=i*(i-1)/2;j++)add(f[i+1][j],f[i][j]),add(f[i+1][j+i+1],mod-f[i][j]);
	}
	for(int i=0;i<=n;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
	jie[0]=1;
	for(int i=1;i<=n;i++)jie[i]=1ll*jie[i-1]*i%mod;
	int ans=0;
	for(int i=0;i<=n;i++){
		for(int j=2;j<=n-i;j++){
			int s=0,res=0;
			for(int k=n*n;~k;k--){
				add(s,f[n-i-1][k+j]);
				res=(res+1ll*f[n-i-1][k]*s%mod)%mod;
			}
//			cout<<1ll*C[n][i]*jie[i]%mod<<endl;
			add(ans,1ll*C[n][i]*jie[i]%mod*res%mod*(n-i-j+1)%mod);
		}
//		cout<<ans<<endl;
	}
	cout<<ans;
}

#include <bits/stdc++.h>
using namespace std;

int n, mod;
int f[510][130000];
int t[510];

void ADD(int &x, int y) {
	x += y;
	if (x >= mod) x -= mod;
}

void SUB(int &x, int y) {
	x -= y;
	if (x < 0) x += mod;
}

int GetF(int x, int y) {
	return (f[x][y] - (y ? f[x][y - 1] : 0) + mod) % mod;
}

int GetS(int x, int y) {
	return f[x][y];
}

int main() {
	cin >> n >> mod;
	f[0][0] = f[1][0] = 1;
	int tot = 0;
	for (int i = 1; i < n; i++) {
		for (int j = 0; j <= tot; j++) {
			ADD(f[i + 1][j], f[i][j]), SUB(f[i + 1][j + i + 1], f[i][j]);
		}
		for (int j = 1; j <= tot; j++) {
			ADD(f[i][j], f[i][j - 1]);
		}
		tot += i;
		for (int j = 1; j <= tot + 1; j++) {
			ADD(f[i + 1][j], f[i + 1][j - 1]);
		}
	}
	tot = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= i; j++) {
			for (int k = j + 1; k <= i; k++) {
				for (int w = k - j + 1; w <= tot; w++) {
					ADD(t[i], 1ll * GetF(i - 1, w) * GetS(i - 1, w - (k - j) - 1) % mod);
				}
			}
		}
		tot += i - 1;
	}
	long long ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = (ans * i + t[i]) % mod;
	}
	cout << ans << endl;
	return 0;
}

#include<iostream>
#include<cstdio>
using namespace std;
const int N=505;
int n;
int MOD;
int f[N][N*N/2],sum[N*N/2];
int dp[N];
int A[N];
int main()
{
    scanf("%d%d",&n,&MOD);
    f[0][0]=sum[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i*(i-1)/2;j++)
            f[i][j]=((long long)sum[j]-(j>min(i-1,j)?sum[j-min(i-1,j)-1]:0)+MOD)%MOD;
        sum[0]=f[i][0];
        for(int j=1;j<=(i+1)*i/2;j++)
            sum[j]=(sum[j-1]+f[i][j])%MOD;
    }
    A[0]=1;
    for(int i=1;i<=n;i++)
        A[i]=1LL*A[i-1]*(n-i+1)%MOD;
    for(int i=1;i<=n;i++)
    {
        sum[0]=f[i][0];
        for(int j=1;j<=n*(n-1)/2;j++)
            sum[j]=(sum[j-1]+f[i][j])%MOD;
        int s=0,sj=0;
        for(int x=2;x<=n*(n-1)/2;x++)
        {
            if(x<=i+1)
            {
                sj=(sj+s)%MOD;
                sj=(sj+2LL*sum[x-2])%MOD;
            }
            else
            {
                sj=(sj+s)%MOD;
                sj=(sj-1LL*sum[x-(i+2)]*(i+2)%MOD+MOD)%MOD;
                sj=(sj+2LL*sum[x-2])%MOD;
            }
            dp[i]=(dp[i]-1LL*f[i][x]*sj%MOD+MOD)%MOD;
            s=(s+sum[x-2])%MOD;
            if(x>i+1) s=((long long)s-sum[x-1-(i+1)]+MOD)%MOD;
            dp[i]=(dp[i]+1LL*f[i][x]*s%MOD*(i+2)%MOD)%MOD;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int sum=1LL*dp[n-i]%MOD;
        ans=(ans+1LL*sum*A[i-1])%MOD;
    }
    printf("%d",ans);
    return 0;
}

/*
AUTHOR: lz.askey
CREATED: 30.07.2021 17:51:42
LANG: C++11
*/
#include <assert.h>

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <iterator>
#include <map>
#include <new>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int> > vii;
typedef long long ll;
#define bit(x, i) (x & (1 << i))
#define in(i, l, r) (l < i && i < r)
#define linr(i, l, r) (l <= i && i <= r)
#define lin(i, l, r) (l <= i && i < r)
#define inr(i, l, r) (l < i && i <= r)
#define gi(a) scanf("%d", &a)
#define gii(a, b) scanf("%d%d", &a, &b)
#define giii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define gs(x) scanf("%s", x)
#define clr(a, x) memset(a, x, sizeof(a))
#define c2i(c) (c - '0')
#define sz(x) ((int)((x).size()))
#define all(c) (c).begin(), (c).end()
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define ff first
#define ss second
// for debug
#define what_is(x) \
  cerr << "Line " << __LINE__ << ": " << #x << " is " << (x) << endl;
#define error(args...)                       \
  {                                          \
    string _s = #args;                       \
    replace(_s.begin(), _s.end(), ',', ' '); \
    stringstream _ss(_s);                    \
    istream_iterator<string> _it(_ss);       \
    err(_it, args);                          \
  }
void err(istream_iterator<string> it) { cerr << endl; }
template <typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << " = " << a << endl;
  err(++it, args...);
}

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int fx[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
const int fxx[8][2] = {{0, 1}, {0, -1}, {1, 0},  {-1, 0},
                       {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};

// struct

// data
int f[55][2005] = {1}, s[55][2005] = {1}, ans[55];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m;
  cin >> n >> m;
  REP(i, 1, n * (n - 1) / 2 + 1) s[0][i] = 1;
  REP(i, 1, n + 1) {
    REP(j, 0, n * (n - 1) / 2 + 1) {
      if (j - i >= 0)
        f[i][j] = (s[i - 1][j] - s[i - 1][j - i] + m) % m;
      else
        f[i][j] = s[i - 1][j];
      s[i][j] = ((j ? s[i][j - 1] : 0) + f[i][j]) % m;
    }
  }
  REP(i, 1, n + 1) {
    REP(j, 1, i + 1) {
      REP(k, j + 1, i + 1) {
        REP(o, 0, (i - 1) * (i - 2) / 2 + 1) {
          int t = o - (k - j) - 1;
          if (t < 0) continue;
          ans[i] = (ans[i] + 1ll * f[i - 1][o] * s[i - 1][t] % m) % m;
        }
      }
    }
  }
  REP(i, 2, n + 1) ans[i] = (ans[i] + 1ll * i * ans[i - 1] % m) % m;
  cout << ans[n] << "\n";
  return 0;
}

/// Fuck Them, Fuck Me, and Fuck You
#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;

#include "bits/stdc++.h"
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>

using namespace __gnu_pbds;
using namespace __gnu_cxx;

using ll = long long;
using ii = pair<int, int>;

typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

#define pb push_back
#define F first
#define S second
#define f(i, a, b)  for(int i = a; i < b; i++)
#define all(a)  a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

const int N = 1e6 + 5, LG = 19, MOD = 998244353;
int n;
int C[555][555];
int cnt[501][1001];
int M;
int cntInv(vector<int> v) {
    int ret = 0;
    for(int i = 0; i < v.size(); i++)
        for(int j = i + 1; j < v.size(); j++)
            ret += (v[i] > v[j]);
    return ret;
}
bool check(vector<int> v, vector<int> v2) {
    return cntInv(v) > cntInv(v2);
}
void solve(int n) {
    vector<int> v;
    f(i,0,n)v.pb(i);
    vector<vector<int>> kollo;
    do {
        kollo.pb(v);
    }while(next_permutation(all(v)));
    int cnt = 0;
    for(int i = 0; i < kollo.size(); i++)
        for(int j = i + 1; j < kollo.size(); j++) {
            cnt += check(kollo[i], kollo[j]);
        }
    cout << cnt << endl;
}
int F[555];
int dp[510 * 510 + 5];
int sum[510 * 510 + 5];
void upd(int n) {
    for(int i = 500 * 500; i >= 0; --i) {
        sum[i] = sum[i+1] + dp[i];
        if(sum[i] >= M)sum[i] -= M;
        dp[i] = sum[i];
        if(i + n <= 500 * 500) {
            dp[i] -= sum[i + n];
            if(dp[i] < 0)
                dp[i] += M;
        }
    }
    sum[0] = dp[0];
    for(int i = 1; i <= 500 * 500; i++) {
        sum[i] = sum[i-1] + dp[i];
        if(sum[i] >= M)sum[i] -= M;
        dp[i] = sum[i];
        if(i > (n - 1)) {
            dp[i] -= sum[i-n];
            if(dp[i] < 0)
                dp[i] += M;
        }
    }
    sum[0] = dp[0];
    for(int i = 1; i <= 500 * 500; i++) {
        sum[i] = sum[i - 1] + dp[i];
        if (sum[i] >= M)sum[i] -= M;
    }

}
void doWork() {
    cin >> n >> M;
    F[0] = 1;

    for(int x = 1; x <= n; x++)
        f(i,0,x)
            f(j,0,x){
                cnt[x][i-j+500] += 1;
            }

    for(int i = 1; i <= n; i++){
        F[i] = 1ll * i * F[i-1] % M;
    }
//    solve(n);
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= i; j++) {
            if(j==0||i==j){
                C[i][j] = 1;
            }   else {
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % M;
            }
        }
    ll ans = 0;
    dp[130000] = 1;
    for(int lcp = n-2; lcp >= 0; lcp--) {
        ll mx = 0;
        upd(n - lcp - 1);
        ll sum = 0;
        for(int i = 0; i < n - lcp; i++)
            for(int j = i + 1; j < n - lcp; j++) {
                sum += ::sum[500 * 500] - ::sum[130000 + j - i];
                if(sum < 0)sum += M;
                if(sum >= M)sum -= M;
            }
//        cout << sum << endl;
        ans = (ans + sum * C[n][lcp] % M * F[lcp]) % M;
    }

    cout << ans << '\n';

}

int32_t main() {
#ifdef ONLINE_JUDGE
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif // ONLINE_JUDGE

    int t = 1;
//    cin >> t;

    while (t--) {
        doWork();
    }

    return 0;
}

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define PI pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define random(a,b) (mtrand()%(b-a+1)+a)
#define PLI pair<ll,int>
#define lc ch[x][0]
#define rc ch[x][1]
#define D(x) #x,x
#define FIO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
void debug() {}
template<class T,class ...U> void debug(const T &head,const U &... tail)
{
    cerr<<head<<(sizeof...(tail)?" ":"\n"),debug(tail...);
}
const int mx=5e1+10;
ll mod=998244353;
mt19937_64 mtrand(time(0));
int n,m,T;
ll dp[mx][3][mx*mx];
int main()
{
    cin>>n>>mod;
    int base=n*(n-1)/2;
    dp[0][1][base]=1;
    for (int i=0;i<n;++i)
    {
        for (int k=-i;k<=i;++k)
        {
            int up=i*(i-1)/2;
            for (int j=-up;j<=up;++j)
            {
                if (k<0)
                {
                    dp[i+1][0][j+base+k]=(dp[i+1][0][j+base+k]+(dp[i][0][j+base]+dp[i][1][j+base]+dp[i][2][j+base])%mod*(i+k+1))%mod;
                }
                else if (k==0)
                {
                    for (int x=0;x<3;++x)
                    {
                        dp[i+1][x][j+base]=(dp[i+1][x][j+base]+dp[i][x][j+base]*(i+1))%mod;
                    }
                }
                else
                {
                    dp[i+1][2][j+base+k]=(dp[i+1][2][j+base+k]+(dp[i][0][j+base]+dp[i][1][j+base]+dp[i][2][j+base])%mod*(i-k+1))%mod;
                }
            }
        }
    }
    ll ans=0;
    for (int i=1;i<=base;++i)
    {
        ans=(ans+dp[n][0][i+base])%mod;
    }
    cout<<ans<<"\n";
}

#include<bits/stdc++.h>

using ll = long long;
using ld = long double;

namespace GTI
{
	char gc(void)
   	{
		const int S = 1 << 16;
		static char buf[S], *s = buf, *t = buf;
		if (s == t) t = buf + fread(s = buf, 1, S, stdin);
		if (s == t) return EOF;
		return *s++;
	}
	ll gti(void)
   	{
		ll a = 0, b = 1, c = gc();
		for (; !isdigit(c); c = gc()) b ^= (c == '-');
		for (; isdigit(c); c = gc()) a = a * 10 + c - '0';
		return b ? a : -a;
	}
	int gts(char *s)
   	{
		int len = 0, c = gc();
		for (; isspace(c); c = gc());
		for (; c != EOF && !isspace(c); c = gc()) s[len++] = c;
		s[len] = 0;
		return len;
	}
	int gtl(char *s)
   	{
		int len = 0, c = gc();
		for (; isspace(c); c = gc());
		for (; c != EOF && c != '\n'; c = gc()) s[len++] = c;
		s[len] = 0;
		return len;
	}
}
using GTI::gti;
using GTI::gts;
using GTI::gtl;

const int N = 550;
int f[N * N], c[N][N], sum[N * N], fct[N];
int main(void)
{
	int n = gti(), M = gti();
	c[0][0] = fct[0] = 1;
	for (int i = 1; i <= n; i++)
	{
		c[i][0] = 1, fct[i] = 1ll * fct[i - 1] * i % M;
		for (int j = 1; j <= i; j++)
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % M;
	}

	f[0] = sum[0] = 1;
	int ans = 0;
	for (int i = 1; i < n; i++)
	{
		int tot = i * (i - 1) / 2;
		for (int j = 0; j <= tot; j++)
		{
			f[j] = sum[j];
			if (j - i >= 0)
				f[j] = (f[j] - sum[j - i]) % M;
		}

		sum[0] = f[0];
		for (int j = 1; j <= tot + i; j++)
			sum[j] = (sum[j - 1] + f[j]) % M;

		int now = 0, x = 2ll * i + 3;
		for (int l = 0; l <= tot; l++)
		{
			for (int r = l + 2; r <= l + i && r <= tot; r++)
			{
				now = (now + 1ll * f[l] * f[r] % M * (-1 - i)) % M;
				if (l & 1)
				{
					now = (now + 1ll * f[l] * f[r] % M * ((x * r + 1) / 2)) % M;
					now = (now - 1ll * f[l] * f[r] % M * ((x * l + 1) / 2)) % M;
					now = (now + 1ll * f[l] * f[r] % M * r * l) % M;
					now = (now - 1ll * f[l] * f[r] % M * ((r * r + 1) / 2)) % M;
					now = (now - 1ll * f[l] * f[r] % M * (l * l / 2)) % M;
				}
				else
				{
					now = (now + 1ll * f[l] * f[r] % M * (x * r / 2)) % M;
					now = (now - 1ll * f[l] * f[r] % M * (x * l / 2)) % M;
					now = (now + 1ll * f[l] * f[r] % M * r * l) % M;
					now = (now - 1ll * f[l] * f[r] % M * (r * r / 2)) % M;
					now = (now - 1ll * f[l] * f[r] % M * (l * l / 2)) % M;
				}
				//now = (now + 1ll * f[l] * f[r] % M * ((2ll * i + 3) * (r - l) / 2)) % M;
				//now = (now + 1ll * f[l] * f[r] % M * (r * l - (r * r + l * l) / 2)) % M;
			}
			if (tot - l > i)
			{
				int cnt = i * (i + 1) / 2;
				now = (now + 1ll * f[l] * (sum[tot] - sum[l + i]) % M * cnt) % M;
			}
		}
		ans = (ans + 1ll * c[n][n - i - 1] * fct[n - i - 1] % M * now) % M;
	}
	printf("%d\n", (ans % M + M) % M);
	return 0;
}

// #pragma GCC target ("avx,avx2")
// #include <bits/extc++.h>
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp> // Common file
// #include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

#define f first
#define s second

using namespace std;
// using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;

// typedef tree<pair<ll, int>, null_type, less<pair<ll, int>>,
// rb_tree_tag, tree_order_statistics_node_update> oset;
//========================================================

const int N = 55;
int n, mod;

ll dp[N][N * N][2][2];

ll solve(int i, int inv, int equal)
{
    if(i == n)
        return inv > 0;

    int bit = (inv >= 0 ? 0 : 1);

    ll &ret = dp[i][abs(inv)][bit][equal];
    if(~ret)
        return ret;

    ret = 0;

    if(!equal)
        for(int j = - (n - i) + 1; j < n - i; j++)
            ret = (ret + 1ll * (n - i - abs(j)) * solve(i + 1, inv + j, 0) %mod) %mod;
    else
    {
        for(int j = 0; j < n - i; j++)
            ret = (ret + 1ll * (n - i - j) * solve(i + 1, inv - j, !j) %mod) %mod;
    }

    return ret;
}

void run_case()
{
    cin >> n >> mod;

    int z = n * n;
    auto valid = [&](int x)
    {
        return (x > -z && x < z);
    };

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

    for(int i=1; i<=n; i++)
    {
        for(int j = -z + 1; j < z; j++)
        {
            int bit = (j >= 0 ? 0 : 1);
            // dp[i][abs(j)][bit];
            if(j == 0) dp[i][0][0][1] = (dp[i][0][0][1] + 1ll * dp[i - 1][0][0][1] * (n - i + 1) %mod) %mod;
            for(int k = -(n - i); k <= n - i; k++)
            {
                int prev = j - k;
                int prevBit = (prev >= 0 ? 0 : 1);

                if(!valid(prev)) continue;

                dp[i][abs(j)][bit][0] = (dp[i][abs(j)][bit][0] + 1ll * (n - i + 1 - abs(k)) * dp[i - 1][abs(prev)][prevBit][0] %mod) %mod;
                if(abs(prev) == 0 && j < 0) dp[i][abs(j)][bit][0] = (dp[i][abs(j)][bit][0] + 1ll * (n - i + 1 - abs(k)) * dp[i - 1][0][0][1] %mod) %mod;
            }
        }
    }

    ll ret = 0;

    for(int j=1; j<z; j++)
        ret = (ret + dp[n][j][0][0]) %mod;

    cout << ret << endl;
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // freopen("input.txt", "rt", stdin);
    // freopen("output.txt", "wt", stdout);
    int T = 1;
    // cin >> T;
    while(T--)
        run_case();
}

// 1000000000

/*
Author: Zcus
Nlog: https://cnblogs.com/zcus
*/

#include <bits/stdc++.h>
using namespace std;

template<class T>
inline T read() {
	T s = 0, w = 1;
	char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') w = -1; c = getchar();}
	while (c >= '0' && c <= '9') { s = s * 10 + (c ^ 48); c = getchar();}
	return s * w;
}

#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ri read<int>
#define pii pair<int, int>
#define rl read<long long>
#define debug(x) cout << #x << " = " << x << endl
#define For(i, x, y) for (int ed = (y), i = (x); i <= ed; i++)
#define Rep(i, x, y) for (int ed = (y), i = (x); i >= ed; i--)
#define ddbug(x, y) cout << #x << " = " << x << " " << #y << " = " << y << "\n"
#define file(FILE_NAME) freopen(FILE_NAME".in", "r", stdin), freopen(FILE_NAME".out", "w", stdout)
#define filein(FILE_NAME) freopen(FILE_NAME".in", "r", stdin);
#define fileout(FILE_NAME) freopen(FILE_NAME".out", "w", stdout);

template<class T> inline bool Chkmax(T& x, const T& y) { return x < y ? x = y, true : false; }
template<class T> inline bool Chkmin(T& x, const T& y) { return x > y ? x = y, true : false; }

const int N = 251 * 501;
const int maxn = 510;

int n, Mod, dp[2][maxn * maxn];
int A[maxn];

int res[maxn * maxn];
int main() {
	n = ri(), Mod = ri();
	A[0] = 1;
	for (int i = 1; i <= n; i++) A[i] = 1ll * A[i - 1] * (n - i + 1) % Mod;
	int ans = 0;
	dp[0][N] = 1;
	for (int i = 1; i < n; i++) {
		memset(dp[i & 1], 0, sizeof dp[i & 1]);
		int now = i & 1;
		int C = (i + 1) * (i + 1) / 2;
		for (int j = N - C; j <= N + C; j++) {
			int w = dp[now ^ 1][j];
			(dp[now][j + i + 1] += w) %= Mod;
			if (j - i + 1 >= 0) (dp[now][j - i + 1] += w) %= Mod;
			(dp[now][j + 1] += 1ll * (Mod - 2) * w % Mod) %= Mod;
		}
		for (int zzm = 1; zzm <= 2; zzm++) {
			for (int j = N + C; j >= N - C; j--) {
				(dp[now][j] += dp[now][j + 1]) %= Mod;
			}
			for (int j = N - C; j <= N + C; j++)
				dp[now][j] = dp[now][j + 1];
		}
		res[C + 1] = 0;
		for (int j = C; j >= 0; j--) res[j] = (res[j + 1] + dp[now][N + j]) % Mod;
		for (int a = 0; a <= i; a++) {
			for (int b = a + 1; b <= i; b++) {
				(ans += 1ll * A[n - i - 1] * res[b - a + 1] % Mod) %= Mod;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long double             ld;
typedef long long int           int64;
typedef unsigned long long int  uint64;
typedef std::pair<int, int>          PII;
typedef std::vector<int>             VI;
typedef std::vector<long long>       VLL;
typedef std::vector<PII>             VII;
typedef std::vector<VI>              VVI;

#define FOR(i, j, k, in)        for (int i = (j); i < (k); i += (in))
#define FORW(i, j, k, in)       for (int i = (j); i <= (k); i += (in))
#define RFOR(i, j, k, in)       for (int i = (j); i >= (k); i -= (in))

#define all(cont)               cont.begin(), cont.end()
#define rall(cont)              cont.rbegin(), cont.rend()
#define sz(cont)                int((cont).size())
#define pb                      push_back
#define mp                      make_pair
#define fi                      first
#define se                      second

#define IINF                    0x3f3f3f3f
#define LLINF                   1000111000111000111LL
#define PI                      3.1415926535897932384626433832795

#define FastIO                  std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); std::cout.tie(NULL);
#define hardio(name)            freopen(name".inp","r",stdin), freopen(name".out","w",stdout);
template<typename T, typename U> istream& operator>>(istream& is, pair<T, U> &p){is >> p.first >> p.second;        return is;}
template<typename T, typename U> ostream& operator<<(ostream& os, pair<T, U>  p){os << p.first << ' ' << p.second; return os;}
const int64 MOD = 1e9 + 7, MOD2 = 998244353;

int64 n;
//int64 ans = 0;

int64 fexp(int64 x, int64 y, int64 m = MOD) {
    int64 a = 1; x %= m;
    while (y) { if (y & 1) a = (x * a) % m; y >>= 1; x = (x * x) % m; }
    return a;
}

int64 inv(int64 x) { return fexp(x, MOD - 2); }

int64 gcd(int64 a, int64 b) { return (a == 0 ? b : gcd(b % a, a)); }
int64 lcm(int64 a, int64 b) { return a / gcd(a, b) * b; }

struct Fenwick {
    int64 F[1006] = {};
    int n = 0;
    void init(int n_) { n = n_; FORW(i, 0, n, 1) F[i] = 0; }
    int query(int x) {
        int64 sum = 0;
        for(x; x > 0; x -= (x & (-x))) sum += F[x];
        return sum;
    }

    void upd(int x) {
        for(x; x <= n; x += (x & (-x))) F[x]++;
    }
};

const int Nmx = 51 * 51 + 20;

int ans[Nmx] = {};
int fac[Nmx], cmb[Nmx][Nmx] = {};
int64 dp[Nmx][Nmx] = {}, f[Nmx][Nmx] = {};

int main(int argc, char* argv[]) {
    FastIO;
#ifndef ONLINE_JUDGE
    hardio("input");
#endif

    int n, mod = MOD; cin >> n >> mod;
    fac[0] = 1;
    FORW(i, 1, n, 1) fac[i] = (1ll * fac[i - 1] * i) % mod;
    FORW(i, 0, n, 1) cmb[i][0] = 1;
    FORW(i, 1, n, 1) FORW(j, 1, i, 1) cmb[i][j] = (1ll * cmb[i - 1][j] + cmb[i - 1][j - 1]) % mod;

    dp[1][0] = 1;
    FORW(i, 1, n - 1, 1) {
        FORW(j, 0, n * n, 1) {
            FORW(k, 0, i, 1) {
                if (j + k <= n * n)
                    dp[i + 1][j + k] = (1ll * dp[i + 1][j + k] + dp[i][j]) % mod;
            }
        }
    }

    FORW(i, 1, n, 1) {
        FORW(j, 0, i * i, 1)
            FORW(k, 0, j - 1, 1) {
                f[i][j - k - 1] = (1ll * f[i][j - k - 1] + 1ll * dp[i][j] * dp[i][k]) % mod;
            }
        RFOR(j, n * n - 1, 0, 1) f[i][j] = (1ll * f[i][j] + f[i][j + 1]) % mod;
    }

    int64 ans2 = 0;
    FORW(i, 1, n, 1) { FORW(j, i + 1, n, 1) {
            FORW(k, 0, i - 1, 1) FORW(l, 0, j - i - 1, 1) FORW(o, 0, n - j, 1) {
                ans2 = (ans2 + 1ll * cmb[i - 1][k] * cmb[j - i - 1][l] % mod
                    * cmb[n - j][o] % mod * f[k + l + o + 1][l + 1] % mod
                    * fac[n - k - l - o - 2] % mod) % mod;
            }
        }
    }

    cout << ans2 << endl;

    return 0;
}

/*
    Author: Nguyen Tan Bao
    Status:
    Idea:
*/

#include <bits/stdc++.h>
#define FI first
#define SE second
#define ALL(a) a.begin(), a.end()
#define SZ(a) int((a).size())
#define MS(s, n) memset(s, n, sizeof(s))
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define FORE(i,a,b) for (int i = (a); i >= (b); i--)
#define FORALL(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define TRAV(x, a) for (auto &x : a)

using namespace std;
using ll = long long; using ld = double;
using pi = pair<int, int>; using pl = pair<ll, ll>; using pd = pair<ld, ld>;
using cd = complex<ld>; using vcd = vector<cd>;

using vi = vector<int>; using vl = vector<ll>;
using vd = vector<ld>; using vs = vector<string>;
using vpi = vector<pi>; using vpl = vector<pl>; using vpd = vector<pd>; // vector<pair>

template<class T> using min_pq = priority_queue<T, vector<T>, greater<T> >;
template<class T> inline int ckmin(T& a, const T& val) { return val < a ? a = val, 1 : 0; }
template<class T> inline int ckmax(T& a, const T& val) { return a < val ? a = val, 1 : 0; }
template<class T> void remDup(vector<T>& v) { sort(ALL(v)); v.erase(unique(ALL(v)), end(v)); }

constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
constexpr int bits(int x) { return x == 0 ? 0 : 31-__builtin_clz(x); } // floor(log2(x))
constexpr int p2(int x) { return 1<<x; }
constexpr int msk2(int x) { return p2(x)-1; }

ll ceilDiv(ll a, ll b) { return a / b + ((a ^ b) > 0 && a % b); } // divide a by b rounded up
ll floorDiv(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); } // divide a by b rounded down
void setPrec(int x) { cout << fixed << setprecision(x); }

// TO_STRING
#define ts to_string
string ts(char c) { return string(1, c); }
string ts(const char* s) { return (string) s; }
string ts(string s) { return s; }
string ts(bool b) { return ts((int)b); }
template<class T> string ts(complex<T> c) { stringstream ss; ss << c; return ss.str(); }
template<class T> using V = vector<T>;
string ts(V<bool> v) {string res = "{"; FOR(i,0,SZ(v)-1) res += char('0'+v[i]); res += "}"; return res; }
template<size_t sz> string ts(bitset<sz> b) { string res = ""; FOR(i,0,SZ(b)-1) res += char('0'+b[i]); return res; }
template<class T, class U> string ts(pair<T,U> p);
template<class T> string ts(T v) { // containers with begin(), end()
    bool fst = 1; string res = "";
    for (const auto& x: v) { if (!fst) res += " "; fst = 0; res += ts(x); }
    return res;
}
template<class T, class U> string ts(pair<T,U> p) { return "("+ts(p.FI)+", "+ts(p.SE)+")"; }

// OUTPUT
template<class T> void pr(T x) { cout << ts(x); }
template<class T, class ...U> void pr(const T& t, const U&... u) { pr(t); pr(u...); }
void ps() { pr("\n"); } // print w/ spaces
template<class T, class ...U> void ps(const T& t, const U&... u) { pr(t); if (sizeof...(u)) pr(" "); ps(u...); }

// DEBUG
void DBG() { cerr << "]" << endl; }
template<class T, class ...U> void DBG(const T& t, const U&... u) { cerr << ts(t); if (sizeof...(u)) cerr << ", "; DBG(u...); }
#define dbg(...) cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define chk(...) if (!(__VA_ARGS__)) cerr << "Line(" << __LINE__ << ") -> function(" \
        << __FUNCTION__  << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", exit(0);

const ld PI = acos(-1.0);
const int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
const ld EPS = 1e-9;
const ll MODBASE = 1000000007LL;
const int INF = 0x3f3f3f3f;

const int MAXN = 110;
const int MAXM = 1000;
const int MAXK = 16;
const int MAXQ = 200010;

int n, mod;

inline int add(int x,int y){int ret=x+y;if(ret>=mod)ret-=mod;return ret;}
inline int sub(int x,int y){int ret=x-y;if(ret<0)ret+=mod;return ret;}
inline int mul(int x,int y){return (x*1ll*y)%mod;}
inline int step(int base,int pw){int ret=1;while(pw){if(pw&1)ret=mul(ret,base);base=mul(base,base);pw>>=1;}return ret;}
inline int invv(int x){return step(x,mod-2);}

int dp[501][124752], dpSum[501][124752], C[501][501], f[501], dpSumRange[124752];

int C2(int n) {
    return n * (n+1) / 2;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    cin >> n >> mod;

    FOR(i,0,n)
        FOR(j,0,i)
            if (j == 0 || j == i) C[i][j] = 1 % mod;
            else C[i][j] = add(C[i-1][j-1], C[i-1][j]);
    f[0] = 1;
    FOR(i,1,n) f[i] = mul(f[i-1], i % mod);

    // dp[i][j] = num of permutations with length i and j inversions
    dp[1][0] = 1 % mod;
    FOR(i,2,n) {
        int invNum = C2(i-1);
        FOR(j,0,invNum) {
            if (j == 0) dpSumRange[j] = dp[i-1][j];
            else dpSumRange[j] = add(dpSumRange[j-1], dp[i-1][j]);
            if (j - i < 0) dp[i][j] = dpSumRange[j];
            else dp[i][j] = sub(dpSumRange[j], dpSumRange[j-i]);
        }
    }

    FOR(i,1,n) {
        int invNum = C2(i-1);
        dpSum[i][0] = dp[i][0];
        FOR(j,1,invNum) {
            dpSum[i][j] = add(dpSum[i][j-1], dp[i][j]);
        }
    }

    int res = 0;
    FOR(used,0,n-1) {
        int remain = n - used;
        int p = 0;
        int N = remain - 1;
        int invNum = C2(N-1);

        FOR(i,2,remain) {
            int z = 0;
            FOR(k,i,invNum) {
                z = add(z, mul(dp[N][k], dpSum[N][k-i]));
            }
            z = mul(z, N - (i-2));
            p = add(p, z);
        }
        p = mul(p, mul(C[n][used], f[used]));
        res = add(res, p);
    }
    cout << res;
    return 0;
}

/* -*- encoding: utf-8 -*-
'''
@File    :   E1.cpp
@Time    :   2021/07/06 15:40:33
@Author  :   puddle_jumper
@Version :   1.0
@Contact :   1194446133@qq.com
'''
# here put the import lib*/
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
	static char c;
	static int f;
	for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
	for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
	x*=f;
}
template<typename T>void write(T x){
	static char q[65];
	int cnt=0;
	if(x<0)pc('-'),x=-x;
	q[++cnt]=x%10,x/=10;
	while(x)
		q[++cnt]=x%10,x/=10;
	while(cnt)pc(q[cnt--]+'0');
}
const int N = 55;
#define int long long
int n;ll mod,f[N][N*N];
ll C[N][N],A[N],sum[N][N*N];
void init(){
	f[1][0] = 1ll;
	rep(i,0ll,N*N)sum[1][i] = 1ll;
	for(int i=2ll;i<=n;i++){
		for(int j=0ll;j<=i*(i-1)/2;j++){
			f[i][j]=sum[i-1][j];
		//	printf("%d %d %d\n",i,j,f[i][j]);
			if(j-i>=0) f[i][j]=(f[i][j]-sum[i-1][j-i]+mod)%mod;
		//	printf("%d %d %d\n",i,j,f[i][j]);
		} sum[i][0]=f[i][0];
		for(int j=1;j<=N*N;j++) sum[i][j]=(sum[i][j-1]+f[i][j])%mod;
	}
	//printf("%lld\n",f[10][5]);
	C[0][0] = 1ll;
	//C[1][1] = C[1][0] = 1ll;
	rep(i,1ll,n){
		rep(j,0ll,i){
			ll now = 0ll;if(j)now = C[i-1][j-1];
			C[i][j] = (C[i-1][j] + now)%mod;
			//printf("%lld\n",C[i][j]);
		}
	}
	A[0] =1ll ;
	rep(i,1ll,n)A[i] = (A[i-1] * i)%mod;
}
int a[N],b[N];

void solve(){
	read(n);read(mod);
	init();
	//枚举前面有几个一样的
	ll ans = 0ll;
	rep(idx,0ll,n-1){
	//	ll idx = n - i;// 后面有idx+1位，
		//枚举u,v
		ll lin = idx*(idx+1)/2;
		ll now = 0ll;
		rep(u,1ll,(idx*(idx-1))/2ll){
			now += (lin%mod*sum[idx][u-1]%mod)%mod*f[idx][u]%mod;
			//printf("%lld %lld %lld\n",idx,u-1,sum[idx][u-1]);
			now %= mod;
			rep(v,max(0ll,u-idx),u-1){
				ll k = ((idx-u+v+1)*(idx-u+v+2)/2%mod*f[idx][v])%mod;
				now = ((now - k*f[idx][u])%mod+mod)%mod;
			}
		}
		ans += (now * C[n][n-idx-1]%mod*A[n-idx-1])%mod;
		ans %= mod;
//		printf("%lld %lld %lld\n",C[n][n-idx-1],A[n-idx-1],);
	}
	write(ans);pc('\n');
}

signed main(){ solve();return 0;}

/// Fuck Them, Fuck Me, and Fuck You
#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;

#include "bits/stdc++.h"
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>

using namespace __gnu_pbds;
using namespace __gnu_cxx;

using ll = long long;
using ii = pair<int, int>;

typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

#define pb push_back
#define F first
#define S second
#define f(i, a, b)  for(int i = a; i < b; i++)
#define all(a)  a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

const int N = 1e6 + 5, LG = 19, MOD = 998244353;
ll dp[55][55* 55];
int n;
int C[55][55];
int M;
ll solve(int n, int inv1, int inv2) {
    if(!n){
        return inv1 > inv2;
    }
    ll &ret = dp[n][inv1-inv2+1500];
    if(~ret)
        return ret;
    ret = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            ret += solve(n-1,inv1 + i, inv2 + j);
    ret %= M;
    return ret;
}
int cntInv(vector<int> v) {
    int ret = 0;
    for(int i = 0; i < v.size(); i++)
        for(int j = i + 1; j < v.size(); j++)
            ret += (v[i] > v[j]);
    return ret;
}
bool check(vector<int> v, vector<int> v2) {
    return cntInv(v) > cntInv(v2);
}
void solve(int n) {
    vector<int> v;
    f(i,0,n)v.pb(i);
    vector<vector<int>> kollo;
    do {
        kollo.pb(v);
    }while(next_permutation(all(v)));
    int cnt = 0;
    for(int i = 0; i < kollo.size(); i++)
        for(int j = i + 1; j < kollo.size(); j++) {
            cnt += check(kollo[i], kollo[j]);
        }
    cout << cnt << endl;
}
int F[555];
void doWork() {
    cin >> n >> M;
    F[0] = 1;
    for(int i = 1; i <= n; i++){
        F[i] = 1ll * i * F[i-1] % M;
    }
//    solve(n);
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= i; j++) {
            if(j==0||i==j){
                C[i][j] = 1;
            }   else {
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % M;
            }
        }
    memset(dp,-1,sizeof dp);
    ll ans = 0;
    for(int lcp = 0; lcp < n; lcp++) {
        ll sum = 0;
        for(int i = 0; i < n - lcp; i++)
            for(int j = i + 1; j < n - lcp; j++) {
                sum += solve(n - lcp - 1, i, j);
            }
        sum %= M;
        ans = (ans + sum * C[n][lcp] % M * F[lcp]) % M;
    }

    cout << ans << '\n';

}

int32_t main() {
#ifdef ONLINE_JUDGE
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif // ONLINE_JUDGE

    int t = 1;
//    cin >> t;

    while (t--) {
        doWork();
    }

    return 0;
}

//People who believe in miracles are as amazing as miracles themselves.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}

const int N=60;
int n,P,fac[N],C[N][N],f[N][N*N/2],g[N][N],ans;

signed main(){
    n=read(),P=read();
    for(int i=(fac[0]=1);i<=n;++i) fac[i]=(ll)fac[i-1]*i%P;
    for(int i=(C[0][0]=1);i<=n;++i)
        for(int j=(C[i][0]=1);j<=i;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
    for(int i=0;i<=n*(n-1)/2;++i) f[1][i]=1;
    for(int i=2;i<=n;++i){
        for(int j=0;j<=i*(i-1)/2;++j){
            f[i][j]=(f[i-1][j]-(j>=i?f[i-1][j-i]:0))%P;
            for(int k=1;k<=i;++k) if(j>k) g[i][k]=(g[i][k]+(ll)f[i][j]*f[i][j-k-1])%P;
            if(j) f[i][j]=(f[i][j]+f[i][j-1])%P;
        }
        for(int j=i*(i-1)/2+1;j<=n*(n-1)/2;++j) f[i][j]=f[i][j-1];
    }
    for(int i=2;i<=n;++i){
        int res=0;
        for(int j=1;j<=i;++j)
            for(int k=j+1;k<=i;++k) res=(res+g[i-1][k-j])%P;
        ans=(ans+(ll)C[n][i]*fac[n-i]%P*res)%P;
    }
    printf("%d",(ans+P)%P);
    return 0;
}

#include<iostream>
#include<cstdio>
using namespace std;
const int N=505;
int n;
int MOD;
int f[N][N*N/2],sum[N*N/2];
int dp[N];
int A[N];
int main()
{
    scanf("%d%d",&n,&MOD);
    f[0][0]=sum[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i*(i-1)/2;j++)
            f[i][j]=((long long)sum[j]-(j>min(i-1,j)?sum[j-min(i-1,j)-1]:0)+MOD)%MOD;
        sum[0]=f[i][0];
        for(int j=1;j<=(i+1)*i/2;j++)
            sum[j]=(sum[j-1]+f[i][j])%MOD;
    }
    A[0]=1;
    for(int i=1;i<=n;i++)
        A[i]=1LL*A[i-1]*(n-i+1)%MOD;
    for(int i=1;i<=n;i++)
    {
        sum[0]=f[i][0];
        for(int j=1;j<=i*(i-1)/2;j++)
            sum[j]=(sum[j-1]+f[i][j])%MOD;
        int s=0,sj=0;
        for(int x=2;x<=i*(i-1)/2;x++)
        {
            if(x<=i+1)
            {
                sj=(sj+s)%MOD;
                sj=(sj+2LL*sum[x-2])%MOD;
            }
            else
            {
                sj=(sj+s)%MOD;
                sj=(sj-1LL*sum[x-(i+2)]*(i+2)%MOD+MOD)%MOD;
                sj=(sj+2LL*sum[x-2])%MOD;
            }
            dp[i]=(dp[i]-1LL*f[i][x]*sj%MOD+MOD)%MOD;
            s=(s+sum[x-2])%MOD;
            if(x>i+1) s=((long long)s-sum[x-1-(i+1)]+MOD)%MOD;
            dp[i]=(dp[i]+1LL*f[i][x]*s%MOD*(i+2)%MOD)%MOD;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int sum=1LL*dp[n-i]%MOD;
        ans=(ans+1LL*sum*A[i-1])%MOD;
    }
    printf("%d",ans);
    return 0;
}

/*
    Author: Nguyen Tan Bao
    Status:
    Idea:
*/

#include <bits/stdc++.h>
#define FI first
#define SE second
#define ALL(a) a.begin(), a.end()
#define SZ(a) int((a).size())
#define MS(s, n) memset(s, n, sizeof(s))
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define FORE(i,a,b) for (int i = (a); i >= (b); i--)
#define FORALL(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define TRAV(x, a) for (auto &x : a)

using namespace std;
using ll = long long; using ld = double;
using pi = pair<int, int>; using pl = pair<ll, ll>; using pd = pair<ld, ld>;
using cd = complex<ld>; using vcd = vector<cd>;

using vi = vector<int>; using vl = vector<ll>;
using vd = vector<ld>; using vs = vector<string>;
using vpi = vector<pi>; using vpl = vector<pl>; using vpd = vector<pd>; // vector<pair>

template<class T> using min_pq = priority_queue<T, vector<T>, greater<T> >;
template<class T> inline int ckmin(T& a, const T& val) { return val < a ? a = val, 1 : 0; }
template<class T> inline int ckmax(T& a, const T& val) { return a < val ? a = val, 1 : 0; }
template<class T> void remDup(vector<T>& v) { sort(ALL(v)); v.erase(unique(ALL(v)), end(v)); }

constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
constexpr int bits(int x) { return x == 0 ? 0 : 31-__builtin_clz(x); } // floor(log2(x))
constexpr int p2(int x) { return 1<<x; }
constexpr int msk2(int x) { return p2(x)-1; }

ll ceilDiv(ll a, ll b) { return a / b + ((a ^ b) > 0 && a % b); } // divide a by b rounded up
ll floorDiv(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); } // divide a by b rounded down
void setPrec(int x) { cout << fixed << setprecision(x); }

// TO_STRING
#define ts to_string
string ts(char c) { return string(1, c); }
string ts(const char* s) { return (string) s; }
string ts(string s) { return s; }
string ts(bool b) { return ts((int)b); }
template<class T> string ts(complex<T> c) { stringstream ss; ss << c; return ss.str(); }
template<class T> using V = vector<T>;
string ts(V<bool> v) {string res = "{"; FOR(i,0,SZ(v)-1) res += char('0'+v[i]); res += "}"; return res; }
template<size_t sz> string ts(bitset<sz> b) { string res = ""; FOR(i,0,SZ(b)-1) res += char('0'+b[i]); return res; }
template<class T, class U> string ts(pair<T,U> p);
template<class T> string ts(T v) { // containers with begin(), end()
    bool fst = 1; string res = "";
    for (const auto& x: v) { if (!fst) res += " "; fst = 0; res += ts(x); }
    return res;
}
template<class T, class U> string ts(pair<T,U> p) { return "("+ts(p.FI)+", "+ts(p.SE)+")"; }

// OUTPUT
template<class T> void pr(T x) { cout << ts(x); }
template<class T, class ...U> void pr(const T& t, const U&... u) { pr(t); pr(u...); }
void ps() { pr("\n"); } // print w/ spaces
template<class T, class ...U> void ps(const T& t, const U&... u) { pr(t); if (sizeof...(u)) pr(" "); ps(u...); }

// DEBUG
void DBG() { cerr << "]" << endl; }
template<class T, class ...U> void DBG(const T& t, const U&... u) { cerr << ts(t); if (sizeof...(u)) cerr << ", "; DBG(u...); }
#define dbg(...) cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define chk(...) if (!(__VA_ARGS__)) cerr << "Line(" << __LINE__ << ") -> function(" \
        << __FUNCTION__  << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", exit(0);

const ld PI = acos(-1.0);
const int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
const ld EPS = 1e-9;
const ll MODBASE = 1000000007LL;
const int INF = 0x3f3f3f3f;

const int MAXN = 110;
const int MAXM = 1000;
const int MAXK = 16;
const int MAXQ = 200010;

int n, mod;

inline int add(int x,int y){int ret=x+y;if(ret>=mod)ret-=mod;return ret;}
inline int sub(int x,int y){int ret=x-y;if(ret<0)ret+=mod;return ret;}
inline int mul(int x,int y){return (x*1ll*y)%mod;}
inline int step(int base,int pw){int ret=1;while(pw){if(pw&1)ret=mul(ret,base);base=mul(base,base);pw>>=1;}return ret;}
inline int invv(int x){return step(x,mod-2);}

int dp[501][124752], dpSum[501][124752], C[501][501], f[501], dpSumRange[124752];

int C2(int n) {
    return n * (n+1) / 2;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    cin >> n >> mod;

    // dp[i][j] = num of permutations with length i and j inversions
    dp[1][0] = 1 % mod;
    FOR(i,2,n) {
        int invNum = C2(i-1);
        FOR(j,0,invNum) {
            if (j == 0) dpSumRange[j] = dp[i-1][j];
            else dpSumRange[j] = add(dpSumRange[j-1], dp[i-1][j]);
            if (j - i < 0) dp[i][j] = dpSumRange[j];
            else dp[i][j] = sub(dpSumRange[j], dpSumRange[j-i]);
        }
    }

    FOR(i,1,n) {
        int invNum = C2(i-1);
        dpSum[i][0] = dp[i][0];
        FOR(j,1,invNum) {
            dpSum[i][j] = add(dpSum[i][j-1], dp[i][j]);
        }
    }

    FOR(i,0,n)
        FOR(j,0,i)
            if (j == 0 || j == i) C[i][j] = 1 % mod;
            else C[i][j] = add(C[i-1][j-1], C[i-1][j]);
    f[0] = 1;
    FOR(i,1,n) f[i] = mul(f[i-1], i % mod);

    int res = 0;
    FOR(used,0,n-1) {
        int remain = n - used;
        int p = 0;
        int N = remain - 1;
        int invNum = C2(N-1);

        vi cnt(remain+1, 0);
        FOR(i,1,remain) {
            FOR(j,i+1,remain) {
                int need = j - i + 1;
                cnt[need]++;
            }
        }

        FOR(i,2,remain) {
            int z = 0;
            FOR(k,i,invNum) {
                z = add(z, mul(dp[N][k], dpSum[N][k-i]));
            }
            z = mul(z, cnt[i]);
            p = add(p, z);
        }
        p = mul(p, mul(C[n][used], f[used]));
        res = add(res, p);
    }
    cout << res;
    return 0;
}

/* Copyright (C) Redouane ELGHAZI
 * TBD
 */
#pragma GCC optimize ("O3")
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#pragma GCC target("avx2")
#define NDEBUG
#endif

#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for (int i = (a); i <= (b); ++i)
#define REPD(i,a,b) for (int i = (a); i >= (b); --i)
#define FORI(i,n) REP(i,1,n)
#define FOR(i,n) REP(i,0,(int)(n)-1)
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define vi vector<int>
#define pll pair<ll, ll>
#define vl vector<ll>
#define ll long long
#define ld long double
#define SZ(x) (int)((x).size())
#define DBG(v) cerr << #v << " = " << (v) << endl;
#define FOREACH(i,t) for (auto i = t.begin(); i != t.end(); ++i)
#define fi first
#define se second

int main(){
	cin.sync_with_stdio(0);
	cin.tie(0);
    ll n, mod;
    cin >> n >> mod;
    vector<vector<ll> > choose(n+1, vector<ll> (n+1, 0));
    choose[0][0] = 1;
    FOR(i,n){
        choose[i+1][0] = 1;
        FOR(j, n){
            choose[i+1][j+1] = (choose[i][j+1]+choose[i][j])%mod;
            //cerr << i+1 << " " << j+1 << " " << choose[i+1][j+1] << endl;
        }
    }
    vector<ll> fact(n+1);
    fact[0] = 1;
    FOR(i,n){
        fact[i+1] = (fact[i]*(i+1))%mod;
        //cerr << i+1 << " " << fact[i+1] << endl;
    }
    ll offset = n*(n+1);
    ll res = 0;
    vector<ll> nb(2*offset, 0), prev(2*offset, 0);
    nb[offset] = 1;
    FOR(i,n-1){
        nb.swap(prev);
        nb = vector<ll> (2*offset, 0);
        FOR(j,i+1){
            for(ll o = -offset; o<offset; ++o){
                if(o+j < offset)
                    nb[offset+o] = (nb[offset+o]+(i+1-j)*prev[offset+o+j])%mod;
                if(j != 0 and o-j >= -offset)
                    nb[offset+o] = (nb[offset+o]+(i+1-j)*prev[offset+o-j])%mod;
            }
        }
        for(ll j = 1; j<i+2; ++j){
            for(ll o = j+1; o<offset; ++o){
                if(o-j > 0){
                    //cerr << i << " " << j << " " << o << " " << choose[n][n-i-2] << " " << fact[n-i-2]*(i+2-j) << " " << nb[offset+o] << endl;
                    res = (res+((choose[n][n-i-2]*fact[n-i-2])%mod)*(((i+2-j)*nb[offset+o])%mod))%mod;
                }
            }
        }
        //cerr << i << " " << res << endl;
        //FOR(i,2*offset) cerr << nb[i] << " ";
        //cerr << endl;

    }
    cout << res << endl;
	return 0;
}

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

const int MAXN=550;
const int B=MAXN*MAXN/2;
ll g[2][B<<1],s[2][B<<1],ans[MAXN];

int main()
{
	ll n,mod;
	int i,j,now,bef,mx;
	scanf("%lld%lld",&n,&mod);
	g[0][B]=s[0][B]=1;
	for(i=B;i<2*B;i++)
		s[0][i]=1;
	for(i=1;i<=n;i++)
	{
		now=i&1;
		bef=now^1;
		memset(g[now],0,sizeof(g[now]));
		memset(s[now],0,sizeof(s[now]));
		mx=i*(i-1)/2;
		g[now][-mx+B]=1;
		for(j=-mx+B+1;j<=mx+B;j++)
		{
			g[now][j]=g[now][j-1]+(s[bef][j+i-1]-s[bef][j-1])-(s[bef][j-1]-s[bef][j-i-1]);
			g[now][j]=(g[now][j]%mod+mod)%mod;
		}
		mx=(i+1)*(i+2)/2;
		for(j=-mx+B;j<=mx+B;j++)
			s[now][j]=(s[now][j-1]+g[now][j])%mod;
		for(j=1;j<i;j++)
			ans[i]=(ans[i]+(s[bef][(i+1)*i/2+B]-s[bef][j+B]+mod)%mod*(i-j))%mod;
		ans[i]=(ans[i]+i*ans[i-1])%mod;
	}
	printf("%lld\n",ans[n]);
}

#include <bits/stdc++.h>
using namespace std;

const int maxn = 55;
int n, P, ans, binom[maxn][maxn], fact[maxn], f[maxn][maxn * maxn];

void red(int &x) {
    x += x >> 31 & P;
}

int main() {
    scanf("%d %d", &n, &P);
    for (int i = fact[0] = 1; i <= n; i++) {
        fact[i] = 1LL * i * fact[i - 1] % P;
    }
    for (int i = 0; i <= n; i++) {
        for (int j = binom[i][0] = 1; j <= i; j++) {
            binom[i][j] = (binom[i - 1][j - 1] + binom[i - 1][j]) % P;
        }
    }
    f[0][n * (n - 1) / 2] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= n * (n - 1); j++) if (f[i - 1][j]) {
            for (int x = 0; x < i; x++) for (int y = 0; y < i; y++) {
                red(f[i][j + x - y] += f[i - 1][j] - P);
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = n * (n - 1); ~j; j--) {
            red(f[i][j] += f[i][j + 1] - P);
        }
    }
    for (int i = 0; i < n; i++) {
        int t = 1LL * binom[n][i] * fact[i] % P;
        for (int x = 1; x <= n - i; x++) {
            for (int y = x + 1; y <= n - i; y++) {
                ans = (ans + 1LL * t * f[n - i - 1][n * (n - 1) / 2 + y - x + 1]) % P;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
constexpr int N=500,bas=N*(N-1)/2+N+10;
int n,mod;
inline void reduce(int &x){if(x>=mod) x-=mod;}
inline void reduce_(int &x){x+=x>>31&mod;}
int C[N+10][N+10],fac[N+10];
void initC(int n){
	C[0][0]=fac[0]=1;
	int i,j;
	for(i=1;i<=n;++i) fac[i]=(long long)fac[i-1]*i%mod;
	for(i=1;i<=n;++i){
		C[i][0]=C[i][i]=1;
		for(j=1;j<i;++j) reduce(C[i][j]=C[i-1][j-1]+C[i-1][j]);
	}
}
int f[(bas<<1)+10],pres[(bas<<1)+10],g[(N<<1)+10];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>mod;
	if(mod==1){
		cout<<0<<'\n';
		return 0;
	}
	initC(n);
	f[bas]=1;
	int i,j,k,ans=0;
	for(i=1;i<=n;++i){
		memset(g,0,sizeof(g));
		for(j=1;j<=i;++j){
			for(k=j+1;k<=i;++k){
				++g[j-k+N];
			}
		}
		for(j=1;j<=bas<<1;++j) reduce(pres[j]=pres[j-1]+f[j]);
		int sum=0;
		for(j=-i;j<=i;++j){
			sum=(sum+(long long)g[j+N]*pres[bas+j-1])%mod;
		}
		ans=(ans+(long long)C[n][n-i]*fac[n-i]%mod*sum)%mod;
		int c=i*(i-1)>>1;
		for(j=-c;j<=c;++j) reduce_(f[bas+j]=pres[bas+j]-pres[bas+j-i]);
		for(j=1;j<=bas<<1;++j) reduce(pres[j]=pres[j-1]+f[j]);
		for(j=-c;j<=c;++j) reduce_(f[bas+j]=pres[bas+j+i-1]-pres[bas+j-1]);
	}
	cout<<ans<<'\n';
	return 0;
}

#include"bits/stdc++.h"
using namespace std;
#define ll long long
ll mod;
ll dp[250005];
ll ans[505];
ll sum[250005];
ll sum2[250005];
ll sum3[250005];
ll lr[505][505];
int main()
{
    int n;
    cin>>n>>mod;
    dp[0]=1%mod;
    for(int i=0;i<505;i++)
    {
        lr[i][i]=i%mod;
        for(int j=i+1;j<505;j++)
        {
            lr[i][j]=(lr[i][j-1]+j)%mod;
        }
    }
    for(int now=2;now<=n;now++)
    {
        //+0 +1 ... +now-1
        int r=now*(now-1)/2;
        ans[now]=ans[now-1]*now%mod;
        memset(sum,0,sizeof(sum));
        memset(sum2,0,sizeof(sum2));
        memset(sum3,0,sizeof(sum3));
        sum[0]=sum2[0]=sum3[0]=dp[0];
        for(int i=1;i<=r+505;i++)
        {
            sum[i]=sum[i-1]+dp[i];
            while(sum[i]>mod)sum[i]-=mod;
            sum2[i]=sum2[i-1]+sum[i];
            while(sum2[i]>mod)sum2[i]-=mod;
            sum3[i]=sum3[i-1]+sum2[i];
            while(sum3[i]>mod)sum3[i]-=mod;
        }
        //for(int i=0;i<=15;i++)printf("%lld%c",sum[i]," \n"[i==15]);
        //for(int i=0;i<=15;i++)printf("%lld%c",sum2[i]," \n"[i==15]);
        //for(int i=0;i<=15;i++)printf("%lld%c",sum3[i]," \n"[i==15]);
        for(int i=0;i<=r;i++)if(dp[i])
        {
            //cout<<"<<"<<i<<" "<<ans[now]<<endl;
            ans[now]+=dp[i]*(sum[r]-sum[i+now])%mod*r%mod;
            //cout<<"<<"<<i<<" "<<ans[now]<<endl;
            //
            //cout<<"??"<<r<<" "<<i+now<<endl;
            //ans[now]+=((sum[i+now]-sum[i+1])*now-())%mod*dp[i]%mod;
            //1 2 3
            /*
            ans[now]+=
            (
            ((sum[i+now]-sum[i+1])*now-(sum2[i+now]-sum2[i+1]-sum[i+1]*(now-1)))-
            ((sum2[i+now]-sum2[i+1])*now-(sum3[i+now]-sum3[i+1]-sum2[i+1]*(now-1)))
             )%mod;*/
             ll temp=0;
             temp+=(now*sum[i+now]-(sum2[i+now]-sum2[i]))%mod*now;
             //cout<<"??"<<temp<<endl;
             temp-=lr[1][now]*sum[i+now]-(now+1)*sum2[i+now]+sum3[i+now];
             //cout<<(now+1)*sum2[i+now]<<endl;
             //cout<<"??"<<temp<<endl;
             if(i)temp+=sum3[i-1];
             //cout<<"??"<<temp<<endl;
             ans[now]+=(temp%mod*dp[i])%mod;
             //ans[now]+=(now*sum[i+now]-(sum2[i+now]-sum2[i]))%mod*now;
             //cout<<"<<"<<i<<" "<<ans[now]<<endl;
             //ans[now]-=lr[1][now]*sum[i+now]-(now+1)*sum2[i+now]+sum3[i+now];//-sum3[i-1];
             //cout<<"<<"<<i<<" "<<ans[now]<<endl;
             //if(i)ans[now]-=sum3[i-1];
             //ans[now]%=mod;
             //cout<<"<<"<<i<<" "<<ans[now]<<endl;
             //sum[i+now]-sum[i+1]
             //sum[i+now]-sum[i+2]
             //
             //now*sum[i+now]-(sum[i+1]+...+sum[i+now])
             //(now*sum[i+now]-(sum2[i+now]-sum2[i]))%mod*now
             //
             //(now*sum[i+now]-sum2[i+now]+sum2[i])
             //(now-1)*sum[i+now]-sum2[i+now]+sum2[i+1]
             //(now-k)*sum[i+now]-sum2[i+now]+sum2[i+k]
             //
             //lr[1][now]*sum[i+now]-(now+1)*sum2[i+now]+sum3[i+now]-sum3[i-1];
            //cout<<"<<"<<i<<" "<<ans[now]<<endl;
            //i+2 i+now
        }
        ans[now]%=mod;
        if(ans[now]<0)ans[now]+=mod;
        for(int i=r;i>=0;i--)dp[i+now]-=dp[i];
        for(int i=1;i<=r+505;i++)
        {
            dp[i]=(dp[i]+dp[i-1])%mod;
            if(dp[i]<0)dp[i]+=mod;
        }
        //0 1 2 3 4 5
        //2 now-1
        //3 now-1 + now-2
        //4 now-1 + now-2 + now-3
        //
        //now+1 = all
        //cout<<now<<endl;
        //for(int i=0;i<=15;i++)printf("%lld%c",dp[i]," \n"[i==15]);
    }
    cout<<ans[n]<<endl;
    return 0;
}

#include<bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define fi first
#define se second
#define pb push_back
#define mp make_pair
using namespace std;
typedef long long ll;
typedef vector<int> vct;
typedef pair<int,int> pii;
const int N=124760;
const int inf=1<<30;
ll read()
{
    ll a=0;
    char b=1,c;
    do if((c=getchar())==45)b=-1;while(c<48||c>57);
    do a=(a<<3)+(a<<1)+(c&15);while((c=getchar())>47&&c<58);
    return a*b;
}
void write(ll x,char c)
{
    if(x<0)putchar(45),x=-x;
    char a[20],s=0;
    do a[++s]=x%10|48;while(x/=10);
    do putchar(a[s]);while(--s);
    putchar(c);
}
int a[N],b[N],c[N],d[N];
int main()
{
    int n=read(),p=read(),ans=0;
    b[0]=c[0]=d[0]=1;
    for(int i=1,s=0;i<n;++i)
    {
        ans=ans*(i+1LL)%p;
        for(int j=0;j<=s;++j)a[j]=b[j];
        for(int j=i;j<=s;++j)a[j]=(a[j]-b[j-i])%p;
        int t=s+i;
        for(int j=1;j<=t;++j)b[j]=(b[j-1]+a[j])%p;
        for(int j=1;j<=s;++j)c[j]=(c[j-1]+b[j])%p;
        for(int j=1;j<=s;++j)d[j]=(d[j-1]+c[j])%p;
        for(int j=2;j<=s;++j)ans=(ans+a[j]*(c[j-2]*(i+1LL)%p-d[j-2]))%p;
        for(int j=i+3;j<=s;++j)ans=(ans+a[j]*1LL*d[j-i-3])%p;
        s=t;
    }
    write((ans+p)%p,'\n');
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int M;

int rep(int x) {
  if (0 <= x && x < M) return x;
  x %= M;
  if (x < 0) x += M;
  return x;
}

int add(int a, int b) {
  a = rep(a); b = rep(b);
  a += b;
  if (a >= M) return a - M;
  if (a < 0) return a + M;
  return a;
}

int mul(int a, int b) {
  a = rep(a); b = rep(b);
  return a * (ll) b % M;
}

void addup(int &a, int b) {
  a = add(a, b);
}

int func(int a) {
  return a * (a - 1) / 2;
}

const int N = 500 + 7;
const int S = N * (N - 1) / 2 + 7;
int n, sol[N], dp[S], sz;
vector<int> ant, sum, grow, scad;

int fsum(int l, int r) {
  if (l > r) return 0;
  return add(sum[r], -sum[l - 1]);
}

int fgrow(int l, int r, int x) {
  if (l > r) return 0;
  int kek = add(grow[r], -grow[l - 1]);
  kek = add(kek, -mul(l, fsum(l, r)));
  kek = add(kek, mul(x, fsum(l, r)));
  return kek;
}

int fscad(int l, int r, int x) {
  if (l > r) return 0;
  int kek = add(scad[r], -scad[l - 1]);
  kek = add(kek, -mul(-l, fsum(l, r)));
  kek = add(kek, mul(x, fsum(l, r)));
  return kek;
}

int main() {
  ///freopen ("input", "r", stdin);
  cin >> n >> M;
  if (M == 1) {
    cout << "0\n";
    return 0;
  }

  dp[0] = 1 % M;
  for (int i = 1; i <= n; i++) {
    int now = i % 2;
    ant = sum = grow = scad = {};
    int extra = func(i + 1);
    int cur = 0;
    for (int j = -extra; j <= extra; j++) {
      ant.push_back(dp[abs(j)]);
      addup(cur, ant.back());
      sum.push_back(cur);
    }
    sz = (int) ant.size();
    int cur1 = 0, cur2 = 0;
    for (int j = 0; j < sz; j++) {
      addup(cur1, mul(j % M, ant[j]));
      addup(cur2, mul(add(0, -(j % M)), ant[j]));
      grow.push_back(cur1);
      scad.push_back(cur2);
    }
    for (int j = 0; j <= func(i); j++) {
      dp[j] = add(fscad(j + extra, j + (i - 1) + extra, i), fgrow(j - (i - 1) + extra, j - 1 + extra, 1));
    }
    for (int dif = 1; dif <= i; dif++) {
      addup(sol[i], mul(i - dif, fsum(dif + 1 + extra, sz - 1)));
    }
  }
  int print = 0;
  for (int i = 1; i <= n; i++) {
    print = add(sol[i], mul(i, print));
  }
  cout << print << "\n";
  return 0;
}

#include <bits/stdc++.h>
#define LL long long
#define ls (p<<1)
#define rs (p<<1|1)
#define INF INT_MAX
#define lowbit(x) (x&-x)
#define ULL unsigned long long
void write(LL x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+48);
}
LL read(){
	LL x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
const int N=55;
int n,f[N][N*N],dp[N],ans,mod,sum[N][N*N],mul[N];
/*
f[i][j]:i个数组成逆序对数量为j时的合法数量
dp[i]:长度为i的序列，第一个数就满足条件的数量
*/
int main(){
#ifdef LOCAL
	freopen("in.in","r",stdin);
	freopen("ans.out","w",stdout);
#endif
	n=read(),mod=read();
	f[0][0]=1;
	for(int i=1;i<=n;++i){
		for(int j=0;j<=i*(i-1)/2;++j){
			for(int k=0;k<=j && k<i;++k){		//加入i后增加的逆序对数量
				f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
			}
			if(!j) sum[i][j]=f[i][j];
			else sum[i][j]=(sum[i][j-1]+f[i][j])%mod;
		}
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=i;++j){					//p的第一个数取j
			for(int k=j+1;k<=i;++k){			//q的第一个数取k，k>j	q比p多了k-j个逆序对
				for(int p=k-j+1;p<=i*(i-1)/2;++p){		//p剩下i-1个数中逆序对数量必须大于k-j
					dp[i]=(dp[i]+1ll*f[i-1][p]*sum[i-1][p-(k-j+1)]%mod)%mod;		//q剩下i-1个数中逆序对数量小于p：q<=p-(k-j+1)
				}
			}
		}
	}
	mul[0]=n;
	for(int i=1;i<=n;++i){
		mul[i]=1ll*mul[i-1]*(n-i)%mod;
	}
	ans=dp[n];
	for(int i=2;i<=n;++i){
		ans=(ans+1ll*dp[n-i+1]*mul[i-2]%mod)%mod;
	}
	write(ans);
	return 0;
}

#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<unordered_set>
#include<map>
#include<unordered_map>
#include<queue>
#include<cmath>
#include<deque>
#include<stack>
#include<iomanip>
#include<random>
#include<cstdio>
#include<string>
#include<cstring>
#include<fstream>
#include<numeric>
#include<bitset>
#include<cassert>

using namespace std;

const long long N = 51, M = 25 * 49 + 1;

long long n, m;
long long dp[N][N][M];
long long d[N][M];
long long p[N][N][M];

inline long long add(long long a, long long b) {
    return (a + b) % m;
}

inline long long mul(long long a, long long b) {
    return a * b % m;
}

void build() {
    dp[1][1][0] = 1;
    d[1][0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= i * (i - 1) / 2; j++) {
            for (int k = 1; k <= min(i, j + 1); k++) {
                dp[i][k][j] = d[i - 1][j - k + 1];
                p[i][k][j] = dp[i][k][j];
                if (j > 0) {
                    p[i][k][j] = add(p[i][k][j - 1], p[i][k][j]);
                }
                d[i][j] = add(d[i][j], dp[i][k][j]);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    //cout << fixed << setprecision(30);
    int _ = 1;
    //cin >> _;
    while (_--) {
        long long ans = 0;
        cin >> n >> m;
        build();
        long long cur = 1;
        for (int i = n; i >= 1; i--) {
            for (int k = 1; k < i; k++) {
                for (int l = k + 1; l <= i; l++) {
                    for (int j = 1; j <= (i - 1) * (i - 2) / 2 + k - 1; j++) {
                        ans = add(ans, mul(cur, mul(dp[i][k][j], p[i][l][j - 1])));
                    }
                }
            }
            cur = mul(cur, i);
        }
        cout << ans << endl;
    }
}

// EXPLOSION!
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#include<chrono>

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<pair<int, int>> vpi;
typedef vector<pair<ll, ll>> vpll;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define mp make_pair
#define rsz resize
#define sz(x) int(x.size())
#define all(x) x.begin(),x.end()
#define f first
#define s second
#define cont continue
#define endl '\n'
//#define ednl '\n'
#define test int testc;cin>>testc;while(testc--)
#define pr(a, b) trav(x,a)cerr << x << b; cerr << endl;
#define message cout << "Hello World" << endl;
const int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 }; // for every grid problem!!
const ll linf = 4000000000000000000LL;
const ll inf = 998244353;//    1000000007

void pv(vi a) { trav(x, a)cout << x << " "; cout << endl; }void pv(vll a) { trav(x, a)cout << x << " "; cout << endl; }void pv(vector<vi>a) {
	F0R(i, sz(a)) { cout << i << endl; pv(a[i]); cout << endl; }
}void pv(vector<vll>a) { F0R(i, sz(a)) { cout << i << endl; pv(a[i]); }cout << endl; }void pv(vector<string>a) { trav(x, a)cout << x << endl; cout << endl; }
void setIO(string s) {
	ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef arwaeystoamneg
	if (sz(s))
	{
		freopen((s + ".in").c_str(), "r", stdin);
		if (s != "test1")
			freopen((s + ".out").c_str(), "w", stdout);
	}
#endif
}
int n, m;
struct mi
{
	int x;
	mi()
	{
		x = 0;
	}
	mi(int y)
	{
		x = y;
	}
	mi operator+(const mi& y)const
	{
		return (x + y.x >= m ? x + y.x - m : x + y.x);
	}
	void operator+=(const mi& y)
	{
		x = (x + y.x >= m ? x + y.x - m : x + y.x);
	}
	mi operator* (const mi& y)const
	{
		return ((ll)x * y.x) % m;
	}
};
int main()
{
	setIO("test1");
	cin >> n >> m;
	int zero = n * n + 5;
	vector<vector<mi>>dp(n + 1, vector<mi>(2 * zero));
	fill(dp[n].begin(), dp[n].begin() + zero, 1);
	R0F(i, n)
	{
		F0R(j, 2 * zero)
		{
			if (j + 0 - (n - i - 1) < 0 || j + (n - i - 1) - 0 >= 2 * zero)continue;
			F0R(k, n - i)
			{
				F0R(l, n - i)
				{
						dp[i][j] += dp[i + 1][j + k - l];
				}
			}
		}
	}
	vector<mi>c(n + 1);
	c[n] = 1;
	R0F(i, n)c[i] = c[i + 1] * (i + 1);
	reverse(all(c));
	mi ans;
	// length of the longest prefix common
	FOR(len, 2, n + 1)
	{
		F0R(j, len)
		{
			F0R(k, j)
			{
				ans += dp[n - len + 1][j - k + zero] * c[n - len];
			}
		}
	}
	cout << ans.x << endl;
}

// This code wrote by chtholly_micromaker(MicroMaker)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define reg register
#define int long long
#define ALL(x) (x).begin(),(x).end()
#define mem(x,y) memset(x,y,sizeof x)
#define sz(x) (int)(x).size()
#define ln putchar('\n')
#define lsp putchar(32)
#define pb push_back
#define MP std::make_pair
#ifdef _LOCAL_
#define dbg(x) std::cerr<<__func__<<"\tLine:"<<__LINE__<<' '<<#x<<": "<<x<<"\n"
#define dprintf(x...) std::fprintf(stderr,x)
#else
#define dbg(x) 42
#define dprintf(x...) 42
#endif
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,b,a) for(int i=(b);i>=(a);--i)
typedef std::pair<int,int> pii;
template <class t> inline void read(t &s){s=0;
reg int f=1;reg char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c))s=(s<<3)+(s<<1)+(c^48),c=getchar();s*=f;return;}
template<class t,class ...A> inline void read(t &x,A &...a){read(x);read(a...);}
template <class t> inline void write(t x){if(x<0)putchar('-'),x=-x;
int buf[21],top=0;while(x)buf[++top]=x%10,x/=10;if(!top)buf[++top]=0;
while(top)putchar(buf[top--]^'0');return;}
inline void setIn(std::string s){freopen(s.c_str(),"r",stdin);return;}
inline void setOut(std::string s){freopen(s.c_str(),"w",stdout);return;}
inline void setIO(std::string s=""){setIn(s+".in");setOut(s+".out");return;}
template <class t>inline bool ckmin(t&x,t y){if(x>y){x=y;return 1;}return 0;}
template <class t>inline bool ckmax(t&x,t y){if(x<y){x=y;return 1;}return 0;}
inline int lowbit(int x){return x&(-x);}
//const int MaxN=505;
const int MaxN=55;

int n,p;
int f[MaxN][MaxN][MaxN*MaxN],fc[MaxN];
struct CC
{
	int f[MaxN][MaxN];
	inline void init()
	{
		f[0][0]=1;
		for(int i=1;i<MaxN;++i)
		{
			f[i][0]=f[i][i]=1;
			for(int j=1;j<=i;++j)
				f[i][j]=(f[i-1][j-1]+f[i-1][j])%p;
		}
	}
	inline int operator () (const int &n,const int &m) const
	{
		if(n<m)return 0;
		return f[n][m];
	}
}C;
inline void add(int &x,int y){(x+=y)>=p&&(x-=p);}
signed main(void)
{
	read(n,p),C.init();
	fc[0]=1;
	for(int i=1;i<=n;++i)fc[i]=1LL*fc[i-1]*(n-i+1)%p;
	f[0][0][0]=1;
	for(int i=0;i<n-1;++i)
		for(int j=0;j<=i;++j)
			for(int k=0;k<=i*i;++k)
				for(int l=0;l<=i+1;++l)
				{
					if(l<=j)
						add(f[i+1][j+1][k+i+1-l],f[i][j][k]);
					else
						add(f[i+1][j][k+i+1-l],f[i][j][k]);
				}
	reg int ans=0;
	// i<3  ans = 0
	for(int i=3;i<n;++i)
		for(int j=0;j<n;++j)
			for(int k=j+1;k<n;++k)
			{
				reg int s=0;
				for(int l=0;l<=i*i;++l)
					add(ans,s*f[i][j][l]%p),
					add(s,f[i][k][l]*fc[n-1-i]%p);
			}
	write(ans),ln;
	return 0;
}

/*
 * Check List:
 * 1. Input / Output File (OI)
 * 2. long long
 * 3. Special Test such as n=1
 * 4. Array Size
 * 5. Memory Limit (OI) int is 4 and longlong is 8
 * 6. Mod (a*b%p*c%p not a*b*c%p  ,  (a-b+p)%p not a-b )
 * 7. Name ( int k; for(int k...))
 * 8. more tests , (T=2 .. more)
 * 9. blank \n after a case
*/

#include <iostream>
#include <string.h>
#include <vector>

using namespace std;

int C[505][505];
int n, mod;

int dp[55][505 * 505];
int prefix_dp[55][505 * 505];

vector<vector<int> > v;

void dfs(int n, int now, vector<int> cur) {
	if (now == 0) {
		vector<int> cur1 = cur;
		v.push_back(cur1);
		return;
	}
	for (int i = 0;i < n;i++) {
		if (now & (1 << i)) {
			cur.push_back(i + 1);
			dfs(n, now ^ (1 << i), cur);
			cur.pop_back();
		}
	}
}

int main(void) {
	scanf("%d %d", &n, &mod);

	C[0][0] = 1;
	for (int i = 1;i <= n;i++) {
		C[i][0] = 1;
		for (int j = 1;j <= i;j++) {
			C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
			C[i][j] %= mod;
		}
	}
	dp[1][0] = dp[0][0] = 1;
	prefix_dp[0][0] = prefix_dp[1][0] = 1;
	for (int i = 0;i <= n;i++) {
		if (i > 0)
			for (int j = 0;j <= i * i;j++) {
				dp[i][j] = prefix_dp[i - 1][j];
				if (j - i + 1 > 0) {
					dp[i][j] -= prefix_dp[i - 1][j - i];
					if (dp[i][j] < 0) dp[i][j] += mod;
				}
			}
		prefix_dp[i][0] = dp[i][0];
		for (int j = 1;j <= n * n;j++) {
			prefix_dp[i][j] = prefix_dp[i][j - 1] + dp[i][j];
			prefix_dp[i][j] %= mod;
		}
	}
	int ret = 0;
	for (int i = 0;i < n;i++) {
		int cur = C[n][i];
		for (int j = 1;j <= i;j++) cur = 1ll * cur * j % mod;
		int tot = 0;
		for (int a = 1;a <= n - i;a++) {
			for (int b = a + 1;b <= n - i;b++) {
				int inv_diff = b - a;
				for (int y = 0;y <= n * n;y++) {
					int sum = 0;
					int sum1 = 0;
					// for (int x = 0;x <= n * n;x++) {
					// 	if (y - x > inv_diff) {
					// 		//tot += 1ll * dp[n - i - 1][x] * dp[n - i - 1][y] % mod;
					// 		sum += dp[n - i - 1][x];
					// 	}
					// }
					if (y - inv_diff - 1 >= 0) {
						sum1 = prefix_dp[n - i - 1][y - inv_diff - 1];
						// if (sum != sum1)
						// 	cout << sum << " " << sum1 << endl;
					}
					// if (sum != sum1) {
					// 	cout << y << " " << y - inv_diff - 1 << " " << n - i - 1 << endl;
					// }
					tot += 1ll * sum1 * dp[n - i - 1][y] % mod;
					// if (y - inv_diff - 1 > 0)
					// 	tot += 1ll * dp[n - i - 1][y] * prefix_dp[n - i - 1][y - inv_diff - 1] % mod;
					tot %= mod;
				}
			}
		}
		ret += 1ll * cur * tot % mod;
		ret %= mod;
	}
	printf("%d\n", ret);
}

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define maxn 105
using namespace std;
int n, f[maxn][maxn * maxn], sum[maxn][maxn * maxn];
int mo;
int fac[maxn];
int c[maxn][maxn];
int main()
{
	scanf("%d%d", &n, &mo);
	fac[0] = fac[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		fac[i] = (ll)fac[i - 1] * i % mo;
	}
	for (int i = 1; i <= n; i++)
	{
		c[i][0] = c[i][i] = 1;
		for (int j = 1; j < i; j++)
		{
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
		}
	}
	f[0][0] = 1;
	for (int i = 0; i <= n * n; i++) sum[0][i] = 1;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j <= n * n; j++)
		{
			f[i][j] = sum[i - 1][j];
			if(j - min(i - 1, j) - 1 >= 0) f[i][j] = (f[i][j] - sum[i - 1][j - min(i - 1, j) - 1] + mo) % mo;
			if(j == 0) sum[i][j] = f[i][j];
			else sum[i][j] = (sum[i][j - 1] + f[i][j]) % mo;
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n - i + 1; j++)
		{
			for (int k = j + 1; k <= n * n; k++)
			{
				int tmp = ans;
				ans = (ans + (ll)fac[i - 1] * c[n][i - 1] % mo * f[n - i][k] % mo * sum[n - i][k - j - 1] % mo * (n - i + 1 - j) % mo) % mo;
//				printf("%d %d %d %d\n", fac[i - 1], calc(n, i - 1) % mo, f[n - i][k] % mo, (ll)sum[n - i][k - j - 1] % mo * (n - i + 1 - j + 1) % mo);
//				printf("%d %d %d %d\n", i, j, k, ans - tmp) % mo;
			}
		}
	}
	printf("%d", ans);
	return 0;
}

// --------------------------------------------------<TEMPLATE>--------------------------------------------------
// --------------------<optimizations>--------------------
/*
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx,avx2,fma")
*/
// -------------------</optimizations>--------------------

// ---------------<Headers and namespaces>----------------
#include <bits/stdc++.h>
using namespace std;

/*
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
*/

// ---------------</Headers and namespaces>---------------

// -----------------<Defines and typedefs>----------------
// typedef tree<int,null_type,less<int>,rb_tree_tag,
// tree_order_statistics_node_update> indexed_set; // use less_equal for multiset
// order_of_key (val): returns the no. of values less than val
// find_by_order (k): returns the iterator to kth largest element.(0-based)

typedef long double LD;
typedef long long ll;
#define int ll
#define pb push_back
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i < b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define FORD(i,a,b) for (int i = a; i >= b; i--)
#define remax(a,b) a = max(a,b)
#define remin(a,b) a = min(a,b)
#define all(v) v.begin(),v.end()
typedef map<int,int> mii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> pii;
typedef vector<pii> vpii;
#define F first
#define S second
#define PQ(type) priority_queue<type>
#define PQD(type) priority_queue<type,vector<type>,greater<type> >
#define WL(t) while(t --)
#define SZ(x) ((int)(x).size())
#define runtime() ((double)clock() / CLOCKS_PER_SEC)
#define inrange(i,a,b) ((i>=min(a,b)) && (i<=max(a,b)))

/*
// -----<SCANF>-----
#define sfi(x) scanf("%d",&x);
#define sfi2(x,y) scanf("%d%d",&x,&y);
#define sfi3(x,y,z) scanf("%d%d%d",&x,&y,&z);

#define sfl(x) scanf("%lld",&x);
#define sfl2(x,y) scanf("%lld%lld",&x,&y);
#define sfl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z);
#define sfl4(x,y,z,x1) scanf("%lld%lld%lld%lld",&x,&y,&z,&x1);
#define sfl5(x,y,z,x1,y1) scanf("%lld%lld%lld%lld%lld",&x,&y,&z,&x1,&y1);
#define sfl6(x,y,z,x1,y1,z1) scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&z,&x1,&y1,&z1);

#define sfs(x) scanf("%s",x);
#define sfs2(x,y) scanf("%s%s",x,y);
#define sfs3(x,y,z) scanf("%s%s%s",x,y,z);
// ----</SCANF>-----

// ----<PRINTF>-----
#define pfi(x) printf("%d\n",x);
#define pfi2(x,y) printf("%d %d\n",x,y);
#define pfi3(x,y,z) printf("%d %d %d\n",x,y,z);

#define pfl(x) printf("%lld\n",x);
#define pfl2(x,y) printf("%lld %lld\n",x,y);
#define pfl3(x,y,z) printf("%lld %lld %lld\n",x,y,z);

#define pfs(x) printf("%s\n",x);
#define pfs2(x,y) printf("%s %s\n",x,y);
#define pfs3(x,y,z) printf("%s %s %s\n",x,y,z);

#define pwe(x) printf("%lld ",x); // print without end
// ----</PRINTF>----
*/
#define FLSH fflush(stdout)
#define fileIO(name) \
    freopen(name".in", "r", stdin); \
    freopen(name".out", "w", stdout);
#define PRECISION(x) cout << fixed << setprecision(x);
#define FAST_IO ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

// ----------------</Defines and typedefs>----------------

// -------------------<Debugging stuff>-------------------
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cout << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ',');cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

// ------------------</Debugging stuff>-------------------

// ------------------------<Consts>-----------------------
const int MAXN = 1000005;
const int SQRTN = 1003;
const int LOGN = 22;
const double PI=acos(-1);

#ifdef int
const int INF=1e16;
#else
const int INF=1e9;
#endif

int MOD = 1000000007;
int FMOD = 998244353;
const double eps = 1e-9;
// -----------------------</Consts>-----------------------

// -------------------------<RNG>-------------------------
mt19937 RNG(chrono::steady_clock::now().time_since_epoch().count());
#define SHUF(v) shuffle(all(v), RNG);
// Use mt19937_64 for 64 bit random numbers.

// ------------------------</RNG>-------------------------

// ----------------------<MATH>---------------------------
template<typename T> T gcd(T a, T b){return(b?__gcd(a,b):a);}
template<typename T> T lcm(T a, T b){return(a*(b/gcd(a,b)));}
int add(int a, int b, int c = MOD){int res=a+b;return(res>=c?res-c:res);}
int mod_neg(int a, int b, int c = MOD){int res;if(abs(a-b)<c)res=a-b;else res=(a-b)%c;return(res<0?res+c:res);}
int mul(int a, int b, int c = MOD){ll res=(ll)a*b;return(res>=c?res%c:res);}
int muln(int a, int b, int c = MOD){ll res=(ll)a*b;return ((res%c)+c)%c;}
ll mulmod(ll a,ll b, ll m = MOD){ll q = (ll)(((LD)a*(LD)b)/(LD)m);ll r=a*b-q*m;if(r>m)r%=m;if(r<0)r+=m;return r;}
template<typename T>T expo(T e, T n){T x=1,p=e;while(n){if(n&1)x=x*p;p=p*p;n>>=1;}return x;}
template<typename T>T power(T e, T n, T m = MOD){T x=1,p=e;while(n){if(n&1)x=mul(x,p,m);p=mul(p,p,m);n>>=1;}return x;}
template<typename T>T extended_euclid(T a, T b, T &x, T &y){T xx=0,yy=1;y=0;x=1;while(b){T q=a/b,t=b;b=a%b;a=t;\
t=xx;xx=x-q*xx;x=t;t=yy;yy=y-q*yy;y=t;}return a;}
template<typename T>T mod_inverse(T a, T n = MOD){T x,y,z=0;T d=extended_euclid(a,n,x,y);return(d>1?-1:mod_neg(x,z,n));}

const int FACSZ = 1; // Make sure to change this

int fact[FACSZ],ifact[FACSZ];

void precom(int c = MOD){
    fact[0] = 1;
    FOR(i,1,FACSZ) fact[i] = mul(fact[i-1],i,c);
    ifact[FACSZ-1] = mod_inverse(fact[FACSZ-1],c);
    REPD(i,FACSZ-1){
        ifact[i] = mul(i+1,ifact[i+1],c);
    }
}

int ncr(int n,int r,int c = MOD){
    return mul(mul(ifact[r],ifact[n-r],c),fact[n],c);
}

// ----------------------</MATH>--------------------------
// --------------------------------------------------</TEMPLATE>--------------------------------------------------

const int INV = 1235;

int dp[55][4*INV][2];

void solvethetestcase();

signed main(){
    // comment when using scanf,printf
    FAST_IO
    int t = 1;
    // (UNCOMMENT FOR MULTIPLE TEST CASES)
    // cin >> t;
    FOR(testcase,1,t+1){
        // (UNCOMMENT FOR CODEJAM)
        // printf("Case #%lld: ",testcase);
        solvethetestcase();
    }
}

int n,mod;

void solvethetestcase(){
    cin >> n >> mod;
    MOD = mod;
    FOR(i,2*INV+1,3*INV){
        dp[n+1][i][1] = 1;
    }
    FORD(i,n,1){
        FOR(d,-INV,INV){
            int m = n+1-i;
            // assuming same permutation till now
            dp[i][d+2*INV][0] = mul(m,dp[i+1][d+2*INV][0]);
            FOR(curd,1,m){
                dp[i][d+2*INV][0] = add(dp[i][d+2*INV][0],mul(m-curd,dp[i+1][d+2*INV-curd][1]));
            }
            // assuming different permutation
            dp[i][d+2*INV][1] = 0;
            for(int curd = -m+1; curd < m; curd++){
                dp[i][d+2*INV][1] = add(dp[i][d+2*INV][1],mul(m-abs(curd),dp[i+1][d+2*INV-curd][1]));
            }
            // if(dp[i][d+2*INV][0]) trace(i,d,0,dp[i][d+2*INV][0]);
            // if(dp[i][d+2*INV][1]) trace(i,d,1,dp[i][d+2*INV][1]);
        }
    }
    cout << dp[1][2*INV][0] << "\n";
}

#include <cmath>
#include <cassert>
#include <iostream>
#include <set>
#include <climits>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <type_traits>
#include <string>
#include <queue>
#include <map>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("Ofast")
#pragma GCC optimization ("unroll-loops")

using namespace std;
int N;
int M;
struct modint {
    modint() : n(0) {}
    template <class T> modint(T n) { n %= M; if (n < 0) n += M; this->n = n; }

    modint & operator+=(const modint &r) { n += r.n; if (n >= M) n -= M; return *this; }
    modint & operator-=(const modint &r) { n -= r.n; if (n < 0) n += M; return *this; }
    modint & operator*=(const modint &r) { n = (int) ((long long) n * r.n % M); return *this; }

    modint & operator--() { if (--n == -1) n = M - 1; return *this; }
    modint & operator++() { if (++n == M) n = 0; return *this; }
    modint operator--(int) { modint t = *this; --*this; return t; }
    modint operator++(int) { modint t = *this; ++*this; return t; }

    modint operator-() const { return 0 - *this; }
    modint operator+() const { return *this; }

    modint pow(long long k = M - 2) const {
        modint f = *this, p = 1;
        while (k > 0) {
            if (k % 2 == 1) f *= p;
            p *= p, k /= 2;
        }
        return f;
    }

    int mod() const { return M; }

    friend modint operator+(modint l, const modint &r) { return l += r; }
    friend modint operator-(modint l, const modint &r) { return l -= r; }
    friend modint operator*(modint l, const modint &r) { return l *= r; }
    friend bool operator==(const modint &l, const modint &r) { return l.n == r.n; }
    friend bool operator!=(const modint &l, const modint &r) { return l.n != r.n; }

    friend ostream & operator<<(ostream &out, const modint &r) { return out << r.n; }

    int n;
};

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> N >> M;
    vector<vector<modint>> combo(N + 1);
    vector<modint> fact = {1};
    while (fact.size() != N + 1) {
        fact.push_back(fact.back() * fact.size());
    }
    for (int i = 0; i <= N; i++) {
        combo[i].assign(N + 1, 0);
    }
    for (int i = 0; i <= N; i++) {
        for (int j = 0; j <= N; j++) {
            if (i < j) {
                combo[i][j] = 0;
                continue;
            }
            if (j == 0) {
                combo[i][j] = 1;
                continue;
            }
            combo[i][j] = combo[i - 1][j - 1] + combo[i - 1][j ];
        }
    }
    const int offset = N * (N - 1)/2;
    modint past_dp[N * N + 1], present_dp[N * N + 1];
    modint pref[N * N + 2];
    modint pref1[N * N + 2];
    past_dp[offset] = 1;
    for (int i = 1; i < N * N + 2; i++) {
        pref[i] = pref[i - 1] + past_dp[i - 1];
        pref1[i] = pref1[i - 1] + past_dp[i - 1] * (i - 1);
    }
    modint ans = 0;
    for (int len = N - 3; len >= 0; len--) {
        int n = N - len - 1;
        for (int k = 0; k < N * (N - 1) + 1; k++) {
            present_dp[k] = n * (pref[k + n] - pref[max(k - n + 1, 0)]) + k * (pref[k + n] - pref[k]) - pref1[k + n] + pref1[k] -  k * (pref[k] - pref[max(k - n + 1, 0)]) + pref1[k] - pref1[max(k - n + 1, 0)];
        }
        pref[0] = pref1[0] = 0;
        for (int i = 1; i < N * N + 2; i++) {
            pref[i] = pref[i - 1] + present_dp[i - 1];
            pref1[i] = pref1[i - 1] + present_dp[i - 1] * (i - 1);
        }
        for (int p = 1; p < N - len; p++) {
            if (offset + 1 + p > N * N + 1 - 1) break;
            ans = ans + (pref[N * N + 1] - pref[offset + 1 + p]) * combo[N][len] * fact[len] * (N - len - p);
        }
        for (int i = 0; i < N * N + 1; i++) {
            swap(past_dp[i], present_dp[i]);
            present_dp[i] = 0;
        }
    }
    cout << ans << '\n';
}

#include <bits/stdc++.h>
//#include <sys/resource.h>
#define initrand mt19937 mt_rand(time(0));
#define rand mt_rand()
#define int long long
#define MOD 1000000007
#define INF 1000000000
#define mid(l, u) ((l+u)/2)
#define rchild(i) (i*2 + 2)
#define lchild(i) (i*2 + 1)
#define mp(a, b) make_pair(a, b)
#define lz lazup(l, u, i);
using namespace std;
const int N = 505;
signed dp[N*N], p[N*N], temp[N*N], nCr[N][N];
int fac[N];
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int n, mod;
    cin>>n>>mod;
    dp[0] =  1;
    dp[0] %= mod;
    fac[0] = 1;
    for(int i = 1;i<N;i++){
        fac[i] = i*fac[i-1];
        fac[i] %= mod;
    }
    nCr[0][0] = 1;
    nCr[0][0] %= mod;
    for(int i = 1;i<N;i++){
        nCr[i][0] = nCr[i][i] = 1;
        nCr[i][i] %= mod;
        for(int j = 1;j<i;j++){
            nCr[i][j] = nCr[i-1][j] + nCr[i-1][j-1];
            nCr[i][j] %= mod;
        }
    }
    int ans = 0;
    for(int i = 1;i<=(n-1);i++){
        //omg
        int sum = 0;
        int maxi = (i*(i-1))/2;
        for(int j = 0;j<=maxi;j++){
            sum += dp[j];
            sum %= mod;
            if((j - i)>=0) sum -= dp[j-i];
            sum += mod;
            sum %= mod;
            temp[j] = sum;
        }
        p[maxi] = dp[maxi] = temp[maxi];
        for(int j = maxi-1;j>=0;j--){
            dp[j] = temp[j];
            p[j] = dp[j] + p[j+1];
            p[j] %= mod;
        }
        //omg
        int b = nCr[n][i+1];
        b *= fac[n-i-1];
        b %= mod;
        int bb = 0;
        int ww = 0;
        for(int k = maxi;k>=0;k--){
            ww -= bb;
            if((k+2) <= maxi) ww += p[k+2]*i;
            ww %= mod;
            ww += mod;
            ww %= mod;

            if((k+i+1)<=maxi) bb -= p[k+i+2];
            if((k+2) <= maxi) bb += p[k+2];
            bb %= mod;
            bb += mod;
            bb %= mod;
            int toAdd = b;
            toAdd *= dp[k];
            toAdd %= mod;
            toAdd *= ww;
            ans += toAdd;
            ans %= mod;
        }
    }
    cout<<ans<<endl;
}

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
const int inf = 1e9; const ll infll = 1e18;

int n; ll mod;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
	cin >> n >> mod;
    vector<ll> fact(n+1,1);
    for(int i=2;i<=n;i++) {
        fact[i] = (fact[i-1]*i)%mod;
    }
    vector<vector<ll>> nck(n+1,vector<ll>(n+1));
    for(int i=0;i<=n;i++) {
        nck[i][0] = 1;
        nck[i][i] = 1;
        for(int j=1;j<i;j++) {
            nck[i][j] = nck[i-1][j-1]+nck[i-1][j];
            if(nck[i][j]>=mod) {
                nck[i][j] -= mod;
            }
        }
    }
    vector<vector<ll>> dp(n+1,vector<ll>(n*n));
    dp[1][0] = 1;
    for(int i=1;i<n;i++) {
        for(int j=0;j<n*n;j++) {
            for(int k=1;k<=i+1;k++) {
                if(dp[i][j]) {
                    int inv = j+(i+1)-k;
                    dp[i+1][inv] += dp[i][j];
                    if(dp[i+1][inv]>=mod) {
                        dp[i+1][inv] -= mod;
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<n*n;j++) {
            dp[i][j] += dp[i][j-1];
            if(dp[i][j]>=mod) {
                dp[i][j] -= mod;
            }
        }
    }
    vector<vector<ll>> a(n+1,vector<ll>(n));
    for(int i=1;i<=n;i++) {
        for(int j=1;j<i;j++) {
            for(int k=j+1;k<n*n;k++) {
                ll x = dp[i-1][k]-dp[i-1][k-1];
                if(x<0) {
                    x += mod;
                }
                ll y = dp[i-1][k-j-1];
                a[i][j] += (x*y)%mod;
                if(a[i][j]>=mod) {
                    a[i][j] -= mod;
                }
            }
        }
    }
    ll ans = 0;
    for(int i=n;i>=4;i--) {
        for(int j=1;j<=n;j++) {
            for(int k=j+1;k<=n;k++) {
                for(int l=1;l<=k-j;l++) {
                    int x = k-j-l;
                    int y = n-i-x;
                    if(x<=n-i&&x<=k-j-1&&y<=n-(k-j)-1&&y<=n-i) {
                        ll z = (nck[k-j-1][x]*nck[n-(k-j)-1][y])%mod;
                        z *= fact[n-i];
                        z %= mod;
                        ans += (z*a[i][l])%mod;
                        if(ans>=mod) {
                            ans -= mod;
                        }
                    }
                }
            }
        }
    }
    cout << ans << "\n";
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define rrep(i, a, b) for (int i = (a); i >= (b); --i)
#define MP make_pair
#define PB push_back
typedef long long LL;
//const LL P = 998244353;
const int N = 505;

int T, n, P;
vector<LL> dp[N];
LL ans[N];

int main() {
    cin >> n >> P;
    dp[1].resize(1), dp[1][0] = 1;
    rep(i, 2, n) {
        int k = i * (i - 1) / 2;
        dp[i].resize(k + 1);
        dp[i][0] = 1;
        rep(j, 1, k) {
            dp[i][j] = dp[i][j - 1];
            if (j <= k - i + 1)
                dp[i][j] = (dp[i][j] + dp[i - 1][j]) % P;
            if (j >= i)
                dp[i][j] = (dp[i][j] - dp[i - 1][j - i] + P) % P;
            //cerr << i << " " << j << " " << dp[i][j] << endl;
        }
    }

    ans[1] = 0;
    rep(m, 2, n) {
        ans[m] = 1ll * ans[m - 1] * m % P;
        rep(diff, 1, m - 1) {
            LL sum = 0, pair = 0;
            int k = (m - 1) * (m - 2) / 2;
            rep(i, 0, k) {
                pair = (pair + dp[m - 1][i] * sum) % P;
                if (i >= diff)
                    sum = (sum + dp[m - 1][i - diff]) % P;
            }
            ans[m] = (ans[m] + pair * (m - diff)) % P;
            //cerr << m << " " << diff << " " << pair << endl;
        }
    }
    cout << ans[n] << endl;
}

/*
Though leaves are many , the root is one.
Through all the lying days of my youth
I swayed my leaves and flowers in the sun.
Now I may wither into the truth.
	  	  	- William Butler Yeats
*/
#include<bits/stdc++.h>
//#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
//using namespace __gnu_pbds;
const int inf=0x3f3f3f3f;
const double eps=1e-6;
typedef long long ll;
#ifndef LOCAL
#define cerr if(0)cout
#define eprintf(...) 0
#else
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#endif
inline string getstr(string &s,int l,int r){string ret="";for(int i=l;i<=r;i++)ret.push_back(s[i]);return ret;}
inline int Rand(){return rand()*32768+rand();}
int n,mod;
int dp[52][52][52*52][2];
const int base=52*26;
inline void add(int &x,int y){
	x+=y;if(x>=mod)x-=mod;
}
void func(int x,int y,int l,int r,int o,int val){
	add(dp[x][y][l][o],val);
	if(val!=0)add(dp[x][y][r+1][o],mod-val);
}
int main(){
	cin>>n>>mod;
	dp[1][0][base][0]=1;
	//0:ny greater
	//1:nx greater
	for(int i=1;i<=n;i++){
		for(int l=0;l<=i;l++){
			for(int t=0;t<52*52;t++)for(int o=0;o<2;o++){
			if(t&&i>1)add(dp[i][l][t][o],dp[i][l][t-1][o]);
			if(dp[i][l][t][o]){
				/*
				for(int nx=0;nx<i;nx++){
					for(int ny=0;ny<i;ny++){
						bool no;
						if(min(nx,ny)<=l&&nx!=ny)no=nx<ny;
						else no=o;
						add(dp[i+1][(nx==ny&&nx<=l)?l+1:min(min(nx,ny),l)][t-nx+ny][no],dp[i][l][t][o]);
					}
				}
				*/
				//nx<ny
				for(int nx=0;nx<i;nx++){
					bool no;
					if(nx<=l)no=1;
					else no=o;
					func(i+1,min(nx,l),t+1,t+(i-1)-nx,no,dp[i][l][t][o]);
				}
				//nx==ny;
				for(int nx=0;nx<i;nx++){
					func(i+1,(nx<=l?l+1:min(nx,l)),t,t,o,dp[i][l][t][o]);
				}
				//nx>ny
				for(int ny=0;ny<i;ny++){
					bool no;
					if(ny<=l)no=0;
					else no=o;
					func(i+1,min(ny,l),t-(i-1)+ny,t-1,no,dp[i][l][t][o]);
				}
			}
			}
		}
	}
	//inv<base
	for(int l=0;l<=n;l++)for(int t=0;t<52*52;t++)for(int o=0;o<2;o++)if(t)add(dp[n+1][l][t][o],dp[n+1][l][t-1][o]);
	int ans=0;
	for(int l=0;l<=n;l++){
		for(int t=0;t<base;t++){
			add(ans,dp[n+1][l][t][1]);
		}
	}
	cout<<ans<<endl;
	return 0;
}

#include <cmath>
#include <deque>
#include <algorithm>
#include <iterator>
#include <list>
#include <tuple>
#include <map>
#include <unordered_map>
#include <queue>
#include <set>
#include <unordered_set>
#include <stack>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <functional>
#include <numeric>
#include <iomanip>
#include <stdio.h>
#include <assert.h>
#include <cstring>
//eolibraries
#define lnf 3999999999999999999
#define inf 999999999
#define fi first
#define se second
#define pb push_back
#define ll long long
#define ld long double
#define all(c) (c).begin(),(c).end()
#define sz(c) (int)(c).size()
#define make_unique(a) sort(all(a)),a.erase(unique(all(a)),a.end())
#define pii pair <int,int>
#define rep(i,n) for(int i = 0 ; i < n ; i++)
#define drep(i,n) for(int i = n-1 ; i >= 0 ; i--)
#define crep(i,x,n) for(int i = x ; i < n ; i++)
#define vi vector <int>
#define vec(...) vector<__VA_ARGS__>
#define _3f4ZxtK ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
//eodefine
using namespace std;

const int mxn=100000;
//snuke's modular int
ll mod;
struct modularint{
	ll x;
	modularint(ll x=0):x(x%mod){}
	modularint& operator+=(const modularint a){
		if ((x += a.x) >= mod) x -= mod;
		return *this;
	}
	modularint& operator-=(const modularint a){
		if ((x += mod-a.x) >= mod) x -= mod;
		return *this;
	}
	modularint& operator*=(const modularint a){
		(x *= a.x) %= mod;
		return *this;
	}
	modularint operator+(const modularint a)const{
		modularint res(*this);
		return res+=a;
	}
	modularint operator-(const modularint a)const{
		modularint res(*this);
		return res-=a;
	}
	modularint operator*(const modularint a)const{
		modularint res(*this);
		return res*=a;
	}
	modularint pow(int n)const{
		modularint res=1,x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modularint inv()const{
		return pow(mod-2);
	}
};
using mint=modularint;

struct combination{
	vec(mint) fact;
	vec(vec(mint)) tablecnk;
	combination(int nupto){
		init(nupto);
	}
	void init(int nupto){
		tablecnk.clear();
		tablecnk.resize(2000,vec(mint)(2000,0));
		fact.resize(mxn+10,0);
		fact[0]=fact[1]=1;
		crep(i,2,mxn){
			mint x=i; fact[i]=fact[i-1]*x;
		}
		rep(i,2000) tablecnk[i][0]=tablecnk[i][i]=1;
		crep(i,1,2000){
			crep(j,1,2000){
				if(j>=i) break;
				tablecnk[i][j]=tablecnk[i-1][j-1]+tablecnk[i-1][j];
			}
		}
	}
	mint cnk(ll k,ll n){
		return tablecnk[n][k].x;
	}
};

int main(){
_3f4ZxtK;
	int n;
	cin>>n>>mod;
	combination comb(mxn);
	vec(vec(mint)) f(n+3,vec(mint)(n*n+3));
	f[1][0]=1;
	crep(i,2,n+1){
		rep(x,i){
			rep(s,n*n){
				if(f[i-1][s].x==0) continue;
				f[i][s+x] += f[i-1][s];
			}
		}
	}
 	mint ans=0;
 	rep(i,n){
 		vec(vec(mint)) dp(n+3,vec(mint)(n*n+3));
		drep(x,n-i){
			mint sum=0;
			dp[x]=dp[x+1];
			rep(s,n*n-x){
				sum+=f[n-i-1][s];
				dp[x][s+x]+=sum;
			}
		}
		rep(x,n-i){
			rep(s,n*n){
				int nows=s+x;
				if(nows>0){
					ans+=f[n-i-1][s]*dp[x+1][nows-1]*comb.cnk(i,n)*comb.fact[i];
				}
			}
		}
	}
	cout<<ans.x<<"\n";
//
	return 0;
}

/*
fi 表示长度为i的排列，p<q且逆序对数p>q的方案数
gij 表示长度为i的排列，任意放，使得p逆序对数比q多j的方案数

f[n] = \sum A_{n,i} * f[n - i] +
g[i][j] =
*/

#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s^'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T t = 0 , tmp[25] = {};
	while(x) tmp[t ++] = x % 10 , x /= 10;
	while(t -- > 0) putchar(tmp[t] + '0');
	putchar(s);
}

const int N = 1250;

LL n , mod , f[55] , g[55][55 * 55] , A[55][55] , tmp[55 * 55];

void Add(LL &x , LL y) {x = (x + y + mod) % mod;}

int main() {
	read(n),read(mod);
	g[2][1251] = 1;
	g[2][1250] = 2;
	g[2][1249] = 1;
	for (int i = 3; i <= n; ++i) {
		Add(f[i] , i * f[i - 1] % mod);
		for (int j = N - (i - 1) * i / 2; j <= N + i * (i - 1) / 2; ++j) {
			for (int k = 1; k < i; ++k) {
				if(j - k >= 0) Add(g[i][j] , g[i - 1][j - k] * (i - k) % mod);
				if(j + k <= N * 2) Add(g[i][j] , g[i - 1][j + k] * (i - k) % mod);
			}
			Add(g[i][j] , g[i - 1][j] * i % mod);
		}
		tmp[0] = 0;
		for (int j = 1; j <= i * (i - 1) / 2; ++j) tmp[j] = g[i - 1][N + j] , Add(tmp[j] , tmp[j - 1]);
		for (int j = 1; j < i; ++j)
			Add(f[i] , (tmp[i * (i - 1) / 2] - tmp[j]) * (i - j) % mod);
	}
	write(f[n]);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <ctime>
#include <cassert>
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
inline int read_int(){
	int t=0;bool sign=false;char c=getchar();
	while(!isdigit(c)){sign|=c=='-';c=getchar();}
	while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
	return sign?-t:t;
}
inline LL read_LL(){
	LL t=0;bool sign=false;char c=getchar();
	while(!isdigit(c)){sign|=c=='-';c=getchar();}
	while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
	return sign?-t:t;
}
inline char get_char(){
	char c=getchar();
	while(c==' '||c=='\n'||c=='\r')c=getchar();
	return c;
}
inline void write(LL x){
	register char c[21],len=0;
	if(!x)return putchar('0'),void();
	if(x<0)x=-x,putchar('-');
	while(x)c[++len]=x%10,x/=10;
	while(len)putchar(c[len--]+48);
}
inline void space(LL x){write(x),putchar(' ');}
inline void enter(LL x){write(x),putchar('\n');}
const int MAXN=505,MAXV=MAXN*MAXN/2,MAXT=MAXV+1e3;
int p[MAXN][MAXV<<1|1],temp[MAXT<<1|1],frac[MAXN];
int main()
{
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	int n=read_int(),mod=read_int();
	p[0][MAXV]=1;
	frac[0]=1;
	_rep(i,1,n){
		frac[i]=1LL*frac[i-1]*(n-i+1)%mod;
		mem(temp,0);
		_rep(j,-MAXV,MAXV){
			temp[j-i+MAXT]=(temp[j-i+MAXT]+p[i-1][j+MAXV])%mod;
			temp[j+1+MAXT]=(temp[j+1+MAXT]-2*p[i-1][j+MAXV]%mod+mod)%mod;
			temp[j+i+2+MAXT]=(temp[j+i+2+MAXT]+p[i-1][j+MAXV])%mod;
		}
		_rep(j,1,MAXT<<1)
		temp[j]=(temp[j-1]+temp[j])%mod;
		_rep(j,1,MAXT<<1)
		temp[j]=(temp[j-1]+temp[j])%mod;
		_rep(j,-MAXV,MAXV)
		p[i][j+MAXV]=temp[j+MAXT];
	}
	_rep(i,0,n){
		for(int j=2*MAXV;j;j--)
		p[i][j-1]=(p[i][j]+p[i][j-1])%mod;
	}
	int ans=0;
	_for(i,0,n-1){
		_for(j,1,n-i)
		ans=(ans+1LL*frac[i]*(n-i-j)%mod*p[n-i-2][j+1+MAXV])%mod;
	}
	enter(ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define forn(i,a,n) for (int i=a; i<n; i++)
#define MOD(x) x%=mod

int n,mod;
int dp[555];
int num[2][308888];
int p[308888],p2[308888];
int num2[308888];

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	cin>>n>>mod;
	dp[1]=0;
	num[0][0]=1;
	int cur=0,nxt=1;
	forn(i,1,n){
		memset(p,0,sizeof p);
		memset(p2,0,sizeof p2);
		memset(num[nxt],0,sizeof num[nxt]);
		int r=0;
		forn(j,1,i*i){
			r+=num[cur][j-1];
			MOD(r);
			p[j]=p[j-1]+r;
			MOD(p[j]);
			p2[j]=p2[j-1]+p[j];
			MOD(p2[j]);
		}
		memset(num2,0,sizeof(num2));
		forn(j,0,300000){
			num2[j+1]=num2[j]+num[cur][j];
			MOD(num2[j+1]);
		}
		forn(j,0,300000){
			num[nxt][j]=num2[j+1]-((j-i)<0?0:num2[j-i])+mod;
			MOD(num[nxt][j]);
		}
		dp[i+1]=dp[i]*(i+1)%mod;
		forn(j,2,i*i){
			if (j-i>=2) dp[i+1]=(dp[i+1]+num[cur][j]*(i*p[j-1]%mod-p2[j-2]+p2[j-i-2]+mod)%mod)%mod;
			else dp[i+1]=(dp[i+1]+num[cur][j]*(i*p[j-1]%mod-p2[j-2]+mod)%mod)%mod;
		}
		swap(cur,nxt);
	}
	cout<<dp[n]<<endl;
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
template<class T,class S=T>inline bool umin(T&m,const S&x){return x<m?m=x,1:0;}
template<class T,class S=T>inline bool umax(T&m,const S&x){return m<x?m=x,1:0;}
auto operator<<(ostream&o,const auto&v)->enable_if_t<!is_constructible_v<string,decltype(v)>,decltype(o<<*end(v))>{int f=0,u=&o==&cerr&&o<<"[";for(auto&&x:v)(f++?o<<(u?", ":" "):o)<<x;return u?o<<"]":o;}
auto operator<<(ostream&o,const auto&t)->decltype(o<<get<0>(t)){o<<"<";apply([&o](auto&...x){int f=0;(((f++?o<<", ":o)<<x),...);},t);return o<<">";}
#ifdef BIZON
    #define rr(...) [](auto&&...x){ cerr << boolalpha << "\e[1;38;5;68m" << #__VA_ARGS__ << " "; int f=0; ((cerr<<"\e[0;38;5;61m"<<",="[!f++]<<"\e[0m "<<x),...)<<endl; }(__VA_ARGS__);
#else
    #define rr(...) 0;
    #define endl '\n'
#endif
#define ALL(c) begin(c), end(c)
#define II(...) __VA_ARGS__; [](auto&...x){(cin>>...>>x);}(__VA_ARGS__);
#define ii(...) int II(__VA_ARGS__)
using ll = long long;

int inv_mod(int a, int m){
    assert(0<a);
    assert(a<m);
    return a==1 ? 1 : m-m*int64_t(inv_mod(m%a, a))/a;
}

template<int &mod> struct modint {
    modint(): x(0) {}
    modint(const auto &val): x(val%mod) { if(x<0) x+=mod; }
    void operator+=(const modint &b){ x+=b.x; if(x>=mod) x-=mod; }
    void operator-=(const modint &b){ x-=b.x; if(x<0) x+=mod; }
    void operator*=(const modint &b){ x = int64_t(x)*b.x %mod; }
    void operator/=(const modint &b){ x = int64_t(x)*inv_mod(b.x,mod) %mod; }
    friend modint operator+(modint a, const modint &b){ a+=b; return a; }
    friend modint operator-(modint a, const modint &b){ a-=b; return a; }
    friend modint operator*(modint a, const modint &b){ a*=b; return a; }
    friend modint operator/(modint a, const modint &b){ a/=b; return a; }
    friend modint operator-(modint a){ if(a.x) a.x = mod - a.x; return a; }
    friend bool operator==(const modint &a, const modint &b){ return a.x==b.x; }
    friend bool operator!=(const modint &a, const modint &b){ return a.x!=b.x; }
    friend ostream& operator<<(ostream &o, const modint &m){ return o<<m.x; }
    explicit operator int(){ return x; }
    private: int x;
};
int mod = 1;
using mint = modint<mod>;

mint operator""m(unsigned long long x){ return mint(x); }

mint mpow(mint a, uint64_t n){
    mint res = 1;
    for(; n; n>>=1, a*=a) if(n&1) res*=a;
    return res;
}

struct Cnk {
    vector<mint> f, fi;
    Cnk(size_t n): f(n+1), fi(n+1){
        f[0] = fi[0] = 1;
        for(size_t i=1; i<=n; ++i) f[i] = f[i-1]*i;
        fi[n] = 1 / f[n];
        for(size_t i=n; i>1; --i) fi[i-1] = fi[i]*i;
    }
    mint operator()(size_t n, size_t k){
        if(n<k) return 0; assert(n<size(f));
        return f[n]*fi[n-k]*fi[k];
    }
};

void convolution_brute(auto a, size_t n, auto b, size_t m, auto ret) {
    fill(ret, ret+n+m-1, 0);
    for(size_t i=0; i<n; ++i)
    for(size_t j=0; j<m; ++j) ret[i+j] += a[i]*b[j];
}

void go_karatsuba(auto a, auto b, auto ret, size_t n) {
    if(n<16) convolution_brute(a, n, b, n, ret); else
    if(n&1) {
        go_karatsuba(a, b, ret, n-1);
        ret[n*2-3] = 0;
        for(size_t i=0; i<n-1; ++i) ret[i+n-1] += a[i]*b[n-1] + b[i]*a[n-1];
        ret[n*2-2] = a[n-1]*b[n-1];
    } else {
        auto ar = a, al = a+n/2, br = b, bl = b+n/2,
        asum = ret+n*5, bsum = asum+n/2,
        x1 = ret, x2 = x1+n, x3 = x2+n;
        for(size_t i=0; i<n/2; ++i) {
            asum[i] = al[i] + ar[i];
            bsum[i] = bl[i] + br[i];
        }
        go_karatsuba(ar, br, x1, n/2);
        go_karatsuba(al, bl, x2, n/2);
        go_karatsuba(asum, bsum, x3, n/2);
        for(size_t i=0; i<n; ++i) x3[i] -= x1[i]+x2[i];
        for(size_t i=0; i<n; ++i) ret[i+n/2] += x3[i];
    }
    ret[n*2-1] = 0;
}

template<class T>
vector<T> convolution(const vector<T> &a, const vector<T> &b) {
    if(size(a) < size(b)) return convolution(b, a);
    if(empty(b)) return {};
    size_t n = size(a), m = size(b);
    if(m < n/m) {
        vector<T> ret(n+m-1);
        convolution_brute(begin(a), n, begin(b), m, begin(ret));
        return ret;
    } else {
        vector<T> ret(n*6), b_ex(n);
        copy(begin(b), end(b), begin(b_ex));
        go_karatsuba(begin(a), begin(b_ex), begin(ret), n);
        return vector<T>(begin(ret), begin(ret)+n+m-1);
    }
}

//count of perm n with k invs
const int MAXN = 501;
vector<mint> ff[MAXN];
vector<mint> ff_suf[MAXN];
vector<mint> conv[MAXN];

mint solve(int n) {
    if(n == 1) return 0;

    mint res = solve(n-1) * n;

    vector<int> cnt(n);
    for(int y=1;y<=n;++y)
    for(int x=1;x<y;++x) cnt[y-x]++;

    int m = size(ff[n-1]) - 1;

    auto &a = ff[n-1];
    auto &b = ff_suf[n-1];

    for(int dxy=1; dxy<=n-1; ++dxy) {

        mint cur = m+dxy+1<size(conv[n-1]) ? conv[n-1][m+(dxy+1)] : 0m;

        res+=cur * cnt[dxy];
    }

    return res;
}

int main() {
    if(auto f="in.txt"; fopen(f,"r") && freopen(f,"r",stdin));
    cin.tie(0)->sync_with_stdio(0);

    ii(N)
    cin>>mod;

    vector<mint> d = {1m};
    ff[0] = d;
	for(int n=1;n<=N;n++) {
		d.push_back(0m);
		for(int i=size(d)-1;i>=0; --i) d[i]+=d[i+1];
		int mx = n*(n-1)/2;
		vector<mint> f(mx+1, 0);
		for(int k=0;k<=mx;++k) {
			int l = max(0, k - (int)size(d) + 1);
			int r = min(n-1, k);
			//for(int i=l; i<=r; ++i) sum+=d[k-i];
			f[k] = d[k-r] - d[k-l+1];
		}
		ff[n] = d = f;
	}

    for(int n=0;n<=N;++n) {
        assert(!empty(ff[n]));
        ff_suf[n] = ff[n];
        ff_suf[n].resize(size(ff[n])+1);
        for(int k=size(ff[n])-1; k>=0; --k)
            ff_suf[n][k] = ff_suf[n][k+1] + ff[n][k];

        auto a = ff[n];
        auto b = ff_suf[n];
        reverse(ALL(a));
        auto c = convolution(a, b);
        conv[n] = c;
    }

    cout<<solve(N)<<endl;

    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>
#include <cassert>
#include <random>
//#include <valarray>
//#include <fstream>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb emplace_back
#define all(x) x.begin(), x.end()
#define sz(x) ((int)(x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define next next239
#define prev prev239
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(abs(x))
#define unq(x) (x.resize(unique(all(x)) - x.begin()))
#define ba back()
#define popcount __builtin_popcountll
#define firstbit(x) (63 - __builtin_clzll(x))
#define fastIO() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);}

#ifdef LOCAL_BOBER
bool local = true;
#define deb(x) cout << #x << " = " << (x) << endl
#define debn(x, n) { cout << #x << "(" << n << ") = " << \
	"{"; int _f_ = 1; rep(_i_, n) {if (!_f_) cout << "|"; cout << x[_i_]; _f_= 0;} cout << "}" << endl;}
#define deba(x) { cout << #x << " (size: " << sz(x) << ") = " << \
	"{"; int _f_ = 1; for (auto o : x) {if (!_f_) cout << "|"; cout << o; _f_ = 0;} cout << "}" << endl;}
#else
bool local = false;
#define deb(x) ;
#define debn(x, n) ;
#define deba(x) ;
#define endl "\n"
#endif

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef pair<double, double> pdd;
typedef long double LD;
typedef double D;

template<class T> void print(T v) { cout << sz(v) << endl; for (auto x : v) cout << x << ' '; cout << endl; };
template<class T> void print1(T v) { cout << sz(v) << endl; for (auto x : v) cout << x + 1 << ' '; cout << endl; };
template<class T1, class T2> ostream& operator << (ostream &o, pair<T1, T2> x) {re o << x.fi << ' ' << x.se;}
template<class T1, class T2> istream& operator >> (istream &o, pair<T1, T2> &x) {re o >> x.fi >> x.se;}
template<class T> ostream& operator << (ostream &o, vector<T> &x) {for (auto &el : x) o << el << ' '; re o;}
template<class T> istream& operator >> (istream &o, vector<T> &x) {for (auto &el : x) o >> el; re o;}
template<class T1, class T2> pair<T1, T2> operator + (pair<T1, T2> a, pair<T1, T2> b) {a.fi += b.fi; a.se += b.se; re a;}
template<class T1, class T2> pair<T1, T2> operator - (pair<T1, T2> a, pair<T1, T2> b) {a.fi -= b.fi; a.se -= b.se; re a;}
template<class T1, class T2> void operator += (pair<T1, T2> &a, pair<T1, T2> b) {a.fi += b.fi; a.se += b.se;}
template<class T1, class T2> void operator -= (pair<T1, T2> &a, pair<T1, T2> b) {a.fi -= b.fi; a.se -= b.se;}

int nint() {int x; cin >> x; re x;}
double getTime() { re clock() / (double) CLOCKS_PER_SEC;};

mt19937 rnd(0);
int rand(int n) { re rnd() % n; }
int rand(int l, int r) { re rnd() % (r - l + 1) + l; }

int mod = 1000000000 + 7;
//const int mod = 998244353;

void initIO() {
	if (local) {
		freopen("input.txt", "r", stdin);
		//freopen("output.txt", "w", stdout);
		srand((int)time(0));
		rnd.seed((int)time(0));
	}
	else {
		//freopen("input.txt", "r", stdin);
		//freopen("output.txt", "w", stdout);
		fastIO();
	}
}

void solve();
void precalc();

int TID;

signed main() {
	initIO();

	int tc = 1;
//	cin >> tc;

//	precalc();
	rep(tt, tc) {
		TID = tt;
//		cout << "Case #" << tt + 1 << ": ";
		solve();
	}

	if (local)
		cout << endl << "time = " << getTime() << endl;
}

/* ================ actual code starts here ================ */

int n;
int m;

int table[55][5050];

int getans(int n, int k) {
	if (k < 0)
		re 0;
	if (k == 0)
		re 1;
	if (n <= 1)
		re 0;

	int &ans = table[n][k];
	if (ans != -1)
		re ans;

	ans = 0;
	rep(i, n) {
		ans += getans(n - 1, k - i);
		if (ans >= mod)
			ans -= mod;
	}
	re ans;
}

int sum[55][5050];
int cnk[55][55];

void precalc() {
	cnk[0][0] = 1;
	for (int n = 1; n <= 50; n++) {
		cnk[n][0] = 1;
		for (int k = 1; k <= n; k++) {
			cnk[n][k] = cnk[n - 1][k - 1] + cnk[n - 1][k];
			if (cnk[n][k] >= mod)
				cnk[n][k] -= mod;
		}
	}

	fill(table, -1);
	for (int i = 1; i <= n; i++)
		for (int j = 0; j <= i * (i - 1) / 2; j++) {
			sum[i][j] = getans(i, j);
			if (j)
				sum[i][j] = (sum[i][j] + sum[i][j - 1]) % mod;
		}
}

void solve() {
	cin >> n >> mod;

	precalc();

	ll ans = 0;
	ll tmp = 1;
	rep(i, n - 2) {
		int m = n - i;
		ll s = 0;
		rep(a, m) rep(b, a) {
			rep(k, (m - 2) * (m - 1) / 2 + 1)
				if (k > a - b) {
//					cout << i << ' ' << a << ' ' << b << ' ' << k << ' ' << sum[m - 1][k - (a - b) - 1] << ' ' << (ll)getans(m - 1, k) << endl;
					s += sum[m - 1][k - (a - b) - 1] * (ll)getans(m - 1, k) % mod;
				}
		}
		s %= mod;
		ans += tmp * s % mod;
		tmp = tmp * (n - i) % mod;
	}
	cout << ans % mod;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;

int M=998244353;
struct modnum{
	int v;
	static int minv(int a,int m){return (a%=m)==1?1:m-ll(minv(m,a))*m/a;}
	modnum():v(0){}
	modnum(ll v_):v(int(v_%M)){if(v<0)v+=M;}
	explicit operator int()const{return v;}
	explicit operator bool()const{return v;}
	friend ostream&operator<<(ostream&out,const modnum&a){return out<<int(a);}
	friend istream&operator>>(istream&in,modnum&a){ll v;in>>v;a=modnum(v);return in;}
	friend bool operator==(const modnum&a,const modnum&b){return a.v==b.v;}
	friend bool operator!=(const modnum&a,const modnum&b){return a.v!=b.v;}
	modnum inv()const{return modnum(minv(v,M));}
	friend modnum inv(const modnum&a){return a.inv();}
	modnum neg()const{return modnum(v?M-v:0);}
	friend modnum neg(const modnum&a){return a.neg();}
	modnum operator-()const{return neg();}
	modnum operator+()const{return *this;}
	modnum&operator++(){if(++v==M)v=0;return*this;}
	modnum&operator--(){if(!v--)v=M-1;return*this;}
	modnum&operator+=(const modnum&a){if((v+=a.v)>=M)v-=M;return*this;}
	modnum&operator-=(const modnum&a){if((v-=a.v)<0)v+=M;return*this;}
	modnum&operator*=(const modnum&a){v=ll(v)*a.v%M;return*this;}
	modnum&operator/=(const modnum&a){return*this*=a.inv();}
	friend modnum operator++(modnum&a,int){modnum r=a;++a;return r;}
	friend modnum operator--(modnum&a,int){modnum r=a;--a;return r;}
	friend modnum operator+(const modnum&a,const modnum&b){return modnum(a)+=b;}
	friend modnum operator-(const modnum&a,const modnum&b){return modnum(a)-=b;}
	friend modnum operator*(const modnum&a,const modnum&b){return modnum(a)*=b;}
	friend modnum operator/(const modnum&a,const modnum&b){return modnum(a)/=b;}
};

typedef modnum mint;

void ProGamerMove(){
	int n;cin>>n>>M;
	const int N=505;
	bool choosedone[N][N]={};
	mint choosedp[N][N];
	function<mint(int,int)>choose=[&](int n,int k){
		if(n<k||k<0)return mint(0);
		if(n==k)return mint(1);
		if(choosedone[n][k])return choosedp[n][k];
		choosedone[n][k]=true;
		return choosedp[n][k]=choose(n-1,k)+choose(n-1,k-1);
	};
	mint F[N];F[0]=1;
	for(int i=1;i<N;++i)F[i]=i*F[i-1];
	int off=n*(n-1)/2;
	vector<mint>dp(2*off+1),tmp(dp),pref(dp);
	#define qp(idx) (idx>=0?pref[idx]:0)
	dp[off]=1;
	mint res=0;
	for(int cn=2;cn<=n;++cn){
//		for(int i=0;i<dp.size();++i)cerr<<setw(3)<<i-off<<" ";cerr<<endl;
//		for(int i=0;i<dp.size();++i)cerr<<setw(3)<<dp[i]<<" ";cerr<<endl;
//		cerr<<endl;
		partial_sum(dp.rbegin(),dp.rend(),pref.rbegin());
		mint prefixes=choose(n,cn)*F[n-cn];
		mint cur;
		for(int i=1;i<=cn;++i)
			for(int j=i+1;j<=cn;++j)
				cur+=pref[j-i+1+off];
		res+=cur*prefixes;
		partial_sum(dp.begin(),dp.end(),tmp.begin());
		partial_sum(tmp.begin(),tmp.end(),pref.begin());
		for(int i=0;i<dp.size()-n+1;++i)dp[i]=qp(i+cn-1)-2*qp(i-1)+qp(i-cn-1);
	}
	cout<<res<<endl;
}

signed main(){
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	int tc=1;
//	cin>>tc;
	while(tc--)ProGamerMove();
}

#define local
//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define all(v) v.begin(),v.end()
#define allr(v) v.rbegin(),v.rend()
#define fori(i,n) for(ll i=0;i<n;i++)
#define ford(i,n) for(ll i = n-1;i >= 0;i--)
#define pb push_back
#define ll long long int
//#define mod 998244353
#define pi pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define fi first
#define se second
#ifdef local
#define debug(x) cout<<#x<<" = "<<x<<endl
#define debug2(x,y) cout<<#x<<" = "<<x<<", "<<#y<<" = "<<y<<endl
#define debug3(x,y,z) cout<<#x<<" = "<<x<<", "<<#y<<" = "<<y<<", "<<#z<<" = "<<z<<endl
#define debug4(x,y,z,q) cout<<#x<<" = "<<x<<", "<<#y<<" = "<<y<<", "<<#z<<" = "<<z<<", "<<#q<<" = "<<q<<endl
#define debugV(v) cout <<#v<<" = ";fori(i,(int) v.size()) {cout << v[i] << " ";} cout << endl << endl;
#define printVector(v) {fori(i,(int) v.size()) {cout << v[i] << " ";} cout << "\n";}
#else
#define debug(x) 1
#define debug2(x,y) 1
#define debug3(x,y,z) 1
#define debug4(x,y,z,q) 1
#define debugV(v) 1
#define printVector(v) {fori(i,(int) v.size()) {cout << v[i] << " ";} cout << "\n";}
#endif
std::mt19937 rng((unsigned int) std::chrono::steady_clock::now().time_since_epoch().count());
using namespace std;
void solve(int ttt)
{
	ll n,mod;
	cin >> n >> mod;
	vector<vector<ll> > dp(n+1,vector<ll> (n*(n-1)/2+1,0));
	for(int i = 1;i <= n;i++) dp[i][0] = 1;
	for(int i = 2;i <= n;i++)
	{
		ll cSum = dp[i][0];
		for(int k = 1;k <= n*(n-1)/2;k++)
		{
			cSum += dp[i-1][k];
			cSum %= mod;
			if(k >= i) cSum -= dp[i-1][k-i];
			cSum += mod;
			cSum %= mod;
			dp[i][k] = cSum;
		}
	}
	vector<vector<ll> > withDiff(n+1,vector<ll> (n*(n-1)+1,0)),pref(n+1,vector<ll> (n*(n-1)+1,0));
	auto get = [&](int l,int r,vector<ll> &v)
	{
		r = min(r,(int)v.size()-1);
		l = max(l,0);
		if(l > r) return 0LL;
		ll res = v[r];
		if(l > 0) res -= v[l-1];
		res += mod;
		res %= mod;
		return res;
	};
	int offset = (n*(n-1))/2;
	withDiff[1][0+offset] = 1;
	for(int k = 0;k <= n*(n-1);k++)
	{
		pref[1][k] += withDiff[1][k];
		if(k) pref[1][k] += pref[1][k-1];
		pref[1][k] %= mod;
	}
	for(int i = 2;i <= n;i++)
	{
		ll res = 0;
		int d = -(i*(i-1))/2;
		int dd = d + offset;
		withDiff[i][dd] = 1;
		d++;
		for(;d <= (i*(i-1)/2);d++)
		{
			res = 0;
			int dd = d + offset;
/*			for(int j = -(i-1);j <= (i-1);j++)
			{
				if(dd+j >= 0 && dd+j <= (n*(n-1)))
				res += (withDiff[i-1][dd + j] * (ll)(i-abs(j)))%mod;
				res %= mod;
			}*/
			res += withDiff[i][dd-1] - get(dd-1-(i-1),dd-1,pref[i-1]) + get(dd,dd+i-1,pref[i-1]);
			res += mod;
			res %= mod;
			withDiff[i][dd] = res;
		}
		for(int k = 0;k <= n*(n-1);k++)
		{
			pref[i][k] += withDiff[i][k];
			if(k) pref[i][k] += pref[i][k-1];
			pref[i][k] %= mod;
		}
	}
/*	for(int i = 1;i <= n;i++)
	{
		for(int j = -(i*(i-1))/2;j <= (i*(i-1))/2;j++)
		{
			cout << withDiff[i][j+offset] << " ";
		}
		cout << "\n";
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = -(i*(i-1))/2;j <= (i*(i-1))/2;j++)
		{
			cout << pref[i][j+offset] << " ";
		}
		cout << "\n";
	}*/
	for(int i = 1;i <= n;i++)
	{
		for(int j = (n*(n-1))-1;j >= 0;j--)
		{
			withDiff[i][j] += withDiff[i][j+1];
			withDiff[i][j]%=mod;
		}
	}
/*	for(int i = 1;i <= n;i++)
	{
		for(int j = -(i*(i-1))/2;j <= (i*(i-1))/2;j++)
		{
			cout << withDiff[i][j+offset] << " ";
		}
		cout << "\n";
	}*/
	vector<ll> ans(n+1,0);
	for(int i = 2;i <= n;i++)
	{
		ll res = 0;
		for(int j = 0;j < i;j++)
		{
			for(int k = j+1;k < i;k++)
			{
				int dd = k - j + 1 + offset;
				if(dd <= n*(n-1))
				res += withDiff[i-1][dd];
				res %= mod;
			}
		}
		res += (ans[i-1] * (i))%mod;
		res %= mod;
		ans[i] = res;
	}
	cout << ans[n] << "\n";
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int ttt;
    ttt = 1;
    //cin >> ttt;
    fori(i,ttt) solve(i);
}

#include <bits/stdc++.h>

using namespace std;

#define ull unsigned long long
#define ll long long
#define ui unsigned int
#define us unsigned short
#define inf_int 1e9
#define inf_ll 1e18
#define smod 998244353

const int maxN = 55;

ll combin[maxN][maxN], fac[maxN];
ll table[maxN][maxN*maxN];
ll n, mod;

int main(){
	ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);

	cin >> n >> mod;

	fill(combin[0], combin[maxN], 0);
	fac[0] = 1;
	for(int x=0;x<maxN;x++){
		combin[x][0] = 1;
	}
	for(int x=1;x<maxN;x++){
		fac[x] = (x * 1ll * fac[x-1]) % mod;
		for(int y=1;y<=x;y++){
			combin[x][y] = (combin[x-1][y-1] + combin[x-1][y]) % mod;
		}
	}

	fill(table[0], table[maxN], 0);
	for(int x=1;x<maxN;x++){
		table[x][0] = 1;
	}
	for(int x=1;x<maxN;x++){
		for(int y=1;y<maxN*maxN;y++){
			ll val = table[x-1][y];
			if(y >= x) val = (val - table[x-1][y-x] + mod) % mod;

			table[x][y] = table[x][y-1]+val;
			table[x][y] %= mod;
//			cout << x << " " << y << " -> " << (table[x][y]-table[x][y-1]+mod) % mod << "\n";
		}
	}

	ll ans = 0;
	for(int x=2;x<=n;x++){
		for(int y=0;y<maxN*maxN;y++){
			ll val = 0;
			for(int z=1;z<=x;z++){
				if(z > 1 && y-z+1 >= 0){
					ans += (table[x-1][y-z+1] - (y-z+1 > 0 ? table[x-1][y-z] : 0) + mod) % mod * val % mod * combin[n][x] % mod * fac[n-x] % mod;
					ans %= mod;
				}

				val += table[x-1][maxN*maxN-1];
				if(val >= mod) val -= mod;
				if(y-z+1 >= 0) val -= table[x-1][y-z+1];
				if(val < 0) val += mod;
			}
		}
	}

	cout << ans << "\n";
    return 0;
}

#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define WT int TT=read();while(TT--)
#define NO puts("NO");
#define YES puts("YES");
using namespace std;

inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}

const int M=55;
int n,Mod,dp1[M][M*M],sum[M][M*M],f[M];
int C2(int n){return n*(n-1)/2;}

signed main()
{
	n=read(),Mod=read();
	dp1[1][0]=1;sum[1][0]=1;
	for (int i=2;i<n;i++)
		for (int j=0;j<=C2(i);j++)
		{
			if (j<i)dp1[i][j]=sum[i-1][min(C2(i-1),j)];
			else dp1[i][j]=(sum[i-1][min(C2(i-1),j)]-sum[i-1][j-i]+Mod)%Mod;
			sum[i][j]=(sum[i][j==0?0:j-1]+dp1[i][j])%Mod;
		}
	for (int i=1;i<=n;i++)
	{
		f[i]=i*f[i-1]%Mod;
//		for (int j=1;j<=i;j++)
//			for (int k=j+1;k<=i;k++)
//				for (int p1=k-j+1;p1<=(i-1)*(i-2)/2;p1++)
//					f[i]=(f[i]+dp1[i-1][p1]*sum[i-1][p1+j-k-1])%Mod;
		for (int j=1;j<=i-1;j++)
			for (int p1=j+1;p1<=C2(i-1);p1++)
				f[i]=(f[i]+dp1[i-1][p1]*sum[i-1][p1-j-1]%Mod*(i-j))%Mod;
	}
	cout<<f[n]<<endl;
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#define N 517
typedef long long ll;
template<typename T> inline void read(T &x) {
	x = 0; char c = getchar(); bool flag = false;
	while (!isdigit(c)) { if (c == '-') flag=  true; c = getchar(); }
	while (isdigit(c)) x = x * 10 + (c ^ 48), c =getchar();
	if (flag)	x = -x;
}
using namespace std;
int P;
inline int Mod(int x) { return x >= P ? x - P : x; }
int n;
int g[2][N * N], gS[N * N];
int C[N][N], jie[N];
inline void init() {
	for (int i = 0; i <= n; ++i) {
		C[i][0] = 1;
		for (int j = 1; j <= i; ++j)
			C[i][j] = Mod(C[i - 1][j - 1] + C[i - 1][j]);
	}
	jie[0] = 1;
	for (int i = 1; i <= n; ++i) jie[i] = 1ll * jie[i - 1] * i % P;
}
int main() {
	read(n), read(P);
	if (P == 1) return puts("0"), 0;
	init();
	int nwt = 0;
	g[nwt][0] = 1;
	int res = 0;
	for (int i = 1; i <= n; ++i) {
		nwt ^= 1;
		memset(g[nwt], 0, sizeof(g[nwt]));
		gS[0] = g[nwt ^ 1][0];
		for (int j = 1; j <= i * i; ++j) gS[j] = Mod(gS[j - 1] + g[nwt ^ 1][j]);
		for (int j = 0; j <= i * i; ++j) {
			g[nwt][j] = Mod(gS[j] - (j - i >= 0 ? gS[j - i] : 0) + P);
			//if (g[nwt][j]) printf("g[%d][%d] = %d\n", i, j, g[nwt][j]);
		}
		for (int j = i * i; j; --j) gS[j] = gS[j - 1];
		gS[0] = 0;
		int tmp = 0;
		int sm0 = 0, sm1 = 0;
		for (int j = 1; j <= i * i; ++j) {
			if (j - i >= 0) sm0 = Mod(sm0 - gS[j - i] + P), sm1 = Mod(sm1 - 1ll * gS[j - i] * j % P + P);
			tmp = (tmp + 1ll * Mod((sm1 - 1ll * j * sm0) % P + P) * g[nwt ^ 1][j]) % P;//bug
			sm0 = Mod(sm0 + gS[j]);
			sm1 = (sm1 + 1ll * gS[j] * (i + j)) % P;
		}
		res = (res + 1ll * C[n][i] * tmp % P * jie[n - i]) % P;//Bug
	}
	printf("%d\n", (res % P + P) % P);
	return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define broken fprintf(stderr, "running on %s %d\n", __FUNCTION__, __LINE__)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define x first
#define y second
#define mp make_pair

typedef pair<int, int> par;
typedef long long LL;
const int N = 55;
int dp[N][N * N * 2], *f[N];
int C[N][N];
int n, mod;

void Add(int &x, int y) { if((x += y) >= mod && (x -= mod)); }

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> mod;
	for(int i = 0; i <= n; i++) {
		C[i][0] = 1;
		for(int j = 1; j <= i; j++) {
			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
		}
	}
	for(int i = 0; i <= n; i++) f[i] = dp[i] + N * N;
	f[1][0] = 1;
	for(int i = 1; i < n; i++) {
		int s = i * (i - 1) / 2;
		for(int j = -s; j <= s; j++) {
			Add(f[i + 1][j], 1ll * f[i][j] * (i + 1) % mod);
			for(int k = 1; k <= i; k++) {
				Add(f[i + 1][j + k], 1ll * f[i][j] * (i + 1 - k) % mod);
				Add(f[i + 1][j - k], 1ll * f[i][j] * (i + 1 - k) % mod);
			}
		}
	}
	for(int i = 1; i <= n; i++) {
		int s = i * (i - 1) / 2;
		for(int j = s - 1; j >= -s; j--) {
			Add(f[i][j], f[i][j + 1]);
		}
	}
	int ans = 0, fac = 1;
	for(int i = 1; i <= n - 2; i++) {
		int s = n - i + 1;
		for(int j = 1; j <= s; j++) {
			Add(ans, 1ll * C[n][i - 1] * fac % mod * (s - j) % mod * f[s - 1][j + 1] % mod);
		}
		fac = 1ll * fac * i % mod;
	}
	cout << ans << endl;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int N = 505;
int dp[N][N*N/2], sum[N][N*N/2];

void init(int n, int mod){
	memset(dp, 0, sizeof(dp));
	dp[0][0] = 1;
	for(int i = 1; i <= n; i++){
		int ti = i*(i - 1)/2;
		for(int p = 0; p <= ti; p++){
			for(int x = 0; x <= i - 1; x++){
				dp[i][p + x] += dp[i - 1][p];
				if(dp[i][p + x] >= mod){
					dp[i][p + x] -= mod;
				}
			}
		}
		for(int j = ti; j >= 0; j--){
			sum[i][j] = dp[i][j] + sum[i][j + 1];
			if(sum[i][j] >= mod)sum[i][j] -= mod;
		}
	}
}

inline int mul(int a, int b, int mod){
	return a*1LL*b%mod;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, mod;
	cin >> n >> mod;

	init(n, mod);
	int answer = 0, eqcnt = 1;
	for(int r = 1; r < n; r++){
		int val = 0, mx = (n - r)*(n - r - 1)/2;
		for(int cs = 0; cs <= mx; cs++){
			for(int dif = 1; dif <= n - r; dif++){
				val += mul(n - r + 1 - dif, mul(dp[n - r][cs], sum[n - r][cs + dif + 1], mod), mod);
				if(val >= mod)val -= mod;
			}
		}
		answer += mul(val, eqcnt, mod);
		if(answer >= mod)answer -= mod;
		eqcnt = eqcnt*1LL*(n - r + 1)%mod;
	}
	cout << answer << '\n';

	return 0;
}

/*input
4 403458273

*/
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<int,null_type,less_equal<int>,rb_tree_tag,tree_order_statistics_node_update> indexed_set;
#pragma GCC optimize("O2","unroll-loops","no-stack-protector")
//order_of_key #of elements less than x
// find_by_order kth element
using ll=long long;
using ld=long double;
using pii=pair<ld,ld>;
#define f first
#define s second
#define pb push_back
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define FILL(n,x) memset(n,x,sizeof(n))
#define ALL(_a) _a.begin(),_a.end()
#define sz(x) (int)x.size()
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()),c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
const ll INF64=1e18+1;
const int INF=0x3f3f3f3f;
ll MOD=998244353;
const ld PI=acos(-1);
const ld eps=1e-3;
#define lowb(x) x&(-x)
#define MNTO(x,y) x=min(x,(__typeof__(x))y)
#define MXTO(x,y) x=max(x,(__typeof__(x))y)
inline ll mult(ll a,ll b){
    if(a>=MOD) a%=MOD;
    if(b>=MOD) b%=MOD;
    return (a*b)%MOD;
}
inline ll mypow(ll a,ll b){
    if(b<=0) return 1;
    ll res=1LL;
    while(b){
        if(b&1) res=mult(res,a);
        a=mult(a,a);
        b>>=1;
    }
    return res;
}
const int maxn=500+5;
const int maxlg=__lg(maxn)+2;
int dp[2*maxn*maxn][2],ndp[2*maxn*maxn][2];
int32_t main(){
    ios::sync_with_stdio(false),cin.tie(0);
    int n;
    cin>>n>>MOD;
    if(n==1){
        cout<<0;
        return 0;
    }
    dp[maxn*maxn][0]=1%MOD;
    for(int i=1;i<n;i++){
        REP(j,2){
            REP(k,2*maxn*maxn){
                if(!dp[k][j]) continue;
                //cout<<i<<' '<<j<<' '<<k-maxn*maxn<<' '<<dp[i][j][k]<<'\n';
                for(int d=-i;d<=i;d++){
                    int cnt=i-abs(d)+1;
                    int t=j;
                    if(d<0) t=1;
                    if(d>0) t=0;
                    ndp[k+d][t]+=((ll)cnt*dp[k][j])%MOD;
                    if(ndp[k+d][t]>=MOD) ndp[k+d][t]-=MOD;
                }
            }
        }
        REP(j,2){
            REP(k,2*maxn*maxn){
                dp[k][j]=ndp[k][j];
                ndp[k][j]=0;
            }
        }
    }
    int ans=0;
    for(int i=maxn*maxn+1;i<2*maxn*maxn;i++){
        ans+=dp[i][1];
        if(ans>=MOD) ans-=MOD;
    }
    cout<<ans;
}

#include<iostream>
#include<cstdio>
#include<vector>
#define int long long
const int N=505;
using namespace std;
int f[2][N*N],ans[N][N],fra[N];
int mod;
inline int read()
{
	char h=getchar();
	int y=0;
	while(h<'0'||h>'9')h=getchar();
	while(h>='0'&&h<='9')y=y*10+h-'0',h=getchar();
	return y;
}
inline void dp(int n)
{
	fra[0]=1;
	for(int i=1;i<=n;i++)fra[i]=1ll*fra[i-1]*(n-i+1)%mod;
	int now=1,pre=0;
	f[0][0]=1;
	for(int i=1;i<=4;i++)f[0][i]=1;
	for(int i=2;i<=n;i++)
	{
//		cout<<i<<"!!\n";
		for(int j=0,fw=i*(i-1)/2;j<=fw;j++)f[now][j]=(f[pre][j]-(j-i<0?0:f[pre][j-i])+mod)%mod;//,cout<<i<<" "<<j<<" "<<f[now][j]<<"!!\n";
		for(int j=i*(i-1)/2+1,fw=i*(i+1)/2;j<=fw;j++)f[now][j]=0;
		for(int j=1,fw=i*(i+1)/2;j<=fw;j++)f[now][j]=(f[now][j]+f[now][j-1])%mod;
		if(i!=n)
		for(int l=2;l<=i+1;l++)
		for(int j=l,fw=i*(i-1)/2;j<=fw;j++)ans[i][l]=(ans[i][l]+1ll*f[now][j-l]*((f[now][j]-f[now][j-1]+mod)%mod)%mod)%mod;

		swap(now,pre);
	}
}
signed main()
{
	int n=read();mod=read();
	dp(n);
	long long aans=0;
	for(int i=0;i<n;i++)
	for(int j=1;j<=n-i;j++)
	for(int z=j+1;z<=n-i;z++)aans=(aans+1ll*fra[i]*ans[n-i-1][z-j+1]%mod)%mod;
	printf("%lld\n",aans);
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=51,M=1255;
int n,mod,f[N][M],sum[N][M],g[N],ans[N];
//f[i][j]:长度为i 逆序对为j对的方案数 枚举最后一个值产生的逆序对数
//sum[i][j]:前缀和
//g[i]:长度为i 第一个位置p<q 保证总逆序对数p>q的方案数
//ans[i]:长度为i p<q 保证总逆序对数p>q的方案数
void add(int &x,int y){
	x+=y;
	x%=mod;
}
int main(){
	scanf("%d%d",&n,&mod);
	add(f[1][0],1);
	add(sum[1][0],f[1][0]);
	for(int i=2;i<=n;++i){
		for(int j=0;j<M;++j){
			for(int k=1;k<=i;++k){
				if(j+i-k<M)add(f[i][j+i-k],f[i-1][j]);
			}
		}
		sum[i][0]=f[i][0];
		for(int j=1;j<M;++j){
			add(sum[i][j],sum[i][j-1]+f[i][j]);
		}
	}
	for(int i=1;i<=n;++i){//长度为i 枚举第一位p<q
		for(int k=1;k<=i;++k){//p
			for(int l=k+1;l<=i;++l){//q
				for(int w=0;w<M;++w){//后面p有w对 q少于w+k-1-(l-1)对
					if(w-(l-1)-1<0)continue;
					add(g[i],1ll*f[i-1][w-(k-1)]*sum[i-1][w-(l-1)-1]%mod);
				}
			}
		}
	}
	for(int i=2;i<=n;++i){
		add(ans[i],(g[i]+1ll*i*ans[i-1]%mod)%mod);
	}
	printf("%d\n",ans[n]);
	return 0;
}

#include"bits/stdc++.h"
using namespace std;

#define int long long
#define pb push_back
#define all(v) begin(v), end(v)
#define ff first
#define ss second
const int inf = 4e18;
const int N = 2e5 + 10;

/*

Let the indexes start from 1.

First for every 1<=i<=n count the number of pairs of permutation of 1~i {p} {q} such that p_1<q_1 and inv(p)>inv(q). Call it t_i.

Enumerate the values of p_1=j and q_1=k, and the number of inversion pairs only in p[2...i] (call it o).
Then, the number of inversion pairs in p is o+j-1, the number of inversion pairs in q should be smaller than that, so the number of inversion pairs only in q[2...i] should be less than o+j-1-k.

Precalculate f(i,j) and s(i,j):
f(i,j) is the number of permutations of 1~i that has exactly j inversion pairs,
s(i,j) is sum_{i=1}^j f(i,j).
This is a famous old problem.

Then the formula is: t_i += f(i-1,o) * s(i-1,o+j-k-1).

Note that the formula only depends on the value of (j-k).
So instead of enumerating j and k, we can only enumerate (j-k), which reduces the complexity from O(n^5) to O(n^4).

After that we calculate the answer. Let ans_i be the answer for i, then it's easy to see:

ans_i= i * ans_{i-1} + t_i.

ans_n is the answer.

The final complexity is O(n^4) with very small constant factors. sample code: https://paste.ubuntu.com/p/d9pbKGDfR6/

some follow up :

We have already made sure p_1<q_1, so here in t_i, p must be lexicographically smaller than q.

Now what if p_1=q_1? That means p_{2...n} and q_{2...n} are also valid abnormal permutation pairs. This is equal to n*ans_{n-1} (since p_1 and q_1 have n choices.)

This explains the final formula ans_i=i*ans_{i-1}+t_{i}.
*/

void testCase() {
   int n, mod; cin >> n >> mod;
   int ma = (n * (n - 1)) / 2;
   int dp[n + 1][ma + 1] = {1}, pref_dp[n + 1][ma + 1] = {};
   for (int i = 0; i <= ma; i++) pref_dp[0][i] = 1;

   for (int i = 1; i <= n; i++) {
      for (int j = 0; j <= ma; j++) {
         int lo = j - i + 1;
         dp[i][j] = (pref_dp[i - 1][j] - (lo > 0 ? pref_dp[i - 1][lo - 1] : 0) + mod) % mod;
         pref_dp[i][j] = (dp[i][j] + (j ? pref_dp[i][j - 1] : 0)) % mod;
      }
   }

   vector<int> pairs(n + 1);

   // p - (k - j) - 1 >= q
   // p : inv(p1[2..i])
   // q : inv(p2[2..i])
   // j : p1[0]
   // k : p2[0]
   // k > j

   for (int i = 1; i <= n; i++) {
      for (int p = 0; p <= ma; p++) {
         for (int diff = 1; diff < i; diff++) {
            if (p - diff - 1 >= 0) {
               int newPairs = ((dp[i - 1][p] * pref_dp[i - 1][p - diff - 1]) % mod * (i - diff)) % mod;
               pairs[i] = (pairs[i] + newPairs) % mod;
            }
         }
      }
   }

   int ans = 0;
   for (int i = 1; i <= n; i++) ans = ((ans * i) % mod + pairs[i]) % mod;
   cout << ans;
}

int32_t main() {
   ios::sync_with_stdio(0); cin.tie(0);
   int t_c = 1;
   // cin >> t_c;
   while (t_c--) testCase();
}

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <tuple>
#include <cmath>
#include <numeric>
#include <functional>
#include <cassert>

#define debug_value(x) cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << #x << "=" << x << endl;
#define debug(x) cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << x << endl;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

using namespace std;
typedef long long ll;

template<typename T>
vector<vector<T>> vec2d(int n, int m, T v){
    return vector<vector<T>>(n, vector<T>(m, v));
}

template<typename T>
vector<vector<vector<T>>> vec3d(int n, int m, int k, T v){
    return vector<vector<vector<T>>>(n, vector<vector<T>>(m, vector<T>(k, v)));
}

template<typename T>
void print_vector(vector<T> v, char delimiter=' '){
    if(v.empty()) {
        cout << endl;
        return;
    }
    for(int i = 0; i+1 < v.size(); i++) cout << v[i] << delimiter;
    cout << v.back() << endl;
}

ll MOD = 1000000007;

class ModInt{
    public:
    ll v;
    ModInt(ll _v = 0){
        if(_v < 0) _v = (_v%MOD)+MOD;
        if(_v >= MOD) _v %= MOD;
        v = _v;
    }
    ModInt operator+(ll n){
        return ModInt((v+n)%MOD);
    }
    ModInt operator-(ll n){
        return ModInt((v-n+MOD)%MOD);
    }
    ModInt operator*(ll n){
        if(n >= MOD) n %= MOD;
        return ModInt((v*n)%MOD);
    }
    ModInt operator/(ll n){
        return ModInt((ModInt(n).inv()*v).v%MOD);
    }

    ModInt &operator+=(ll n){
        v = (v+n)%MOD;
        return *this;
    }
    ModInt &operator-=(ll n){
        v = (v-n+MOD)%MOD;
        return *this;
    }
    ModInt &operator*=(ll n){
        v = (v*n+MOD)%MOD;
        return *this;
    }

    ModInt operator+(ModInt n){
        return ModInt((v+n.v)%MOD);
    }
    ModInt operator-(ModInt n){
        return ModInt((v-n.v+MOD)%MOD);
    }
    ModInt operator*(ModInt n){
        return ModInt((v*n.v)%MOD);
    }
    ModInt operator/(ModInt n){
        return ModInt((n.inv()*v).v%MOD);
    }

    ModInt &operator+=(ModInt n){
        v = (v+n.v)%MOD;
        return *this;
    }
    ModInt &operator-=(ModInt n){
        v = (v-n.v+MOD)%MOD;
        return *this;
    }
    ModInt &operator*=(ModInt n){
        v = (v*n.v)%MOD;
        return *this;
    }

    bool operator==(ModInt n){
        return v == n.v;
    }
    bool operator!=(ModInt n){
        return v != n.v;
    }
    ModInt &operator=(ll n){
        v = n%MOD;
        return *this;
    }

    ModInt inv(){
        if(v == 1) return ModInt(1);
        else return ModInt(MOD-ModInt(MOD%v).inv().v*(MOD/v)%MOD);
    }
};

ostream& operator<<(ostream& os, const ModInt& m){
    os << m.v;
    return os;
}

istream & operator >> (istream &in,  ModInt &m){
    in >> m.v;
    return in;
}

ModInt pow(ModInt a, ll n) {
    assert(n >= 0);
	ModInt ans = 1;
    while (n > 0) {
        if (n&1) ans = ans*a;
        a = a*a;
        n >>= 1;
    }
	return ans;
}

template<typename T>
class CumsumGrid{
    public:
    CumsumGrid(vector<vector<T>> v): v(v){
        n = v.size();
        m = v[0].size();
        v_cumsum = vector<vector<T>>(n+1, vector<T>(m+1, T(0)));
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++){
                v_cumsum[i+1][j+1] = v_cumsum[i+1][j]+v_cumsum[i][j+1]-v_cumsum[i][j]+v[i][j];
            }
        }
    }
    /**
     * v[l] + ... + v[r-1]
     */
    T sum(int il, int ir, int jl, int jr){
        if(ir <= il) return T(0);
        if(jr <= jl) return T(0);
        if(ir > n) ir = n;
        if(jr > m) jr = m;
        if(il < 0) il = 0;
        if(jl < 0) jl = 0;
        return v_cumsum[ir][jr]-v_cumsum[ir][jl]-v_cumsum[il][jr]+v_cumsum[il][jl];
    }
    private:
    int n, m;
    vector<vector<T>> v;
    vector<vector<T>> v_cumsum;
};

const int N_MAX = 1000;
ModInt cb[1005][1005], fac[1005];

void init(){
    cb[0][0] = 1;
    fac[0] = 1;
    for(int n = 1; n <= N_MAX; n++){
        cb[n][0] = 1;
        fac[n] = fac[n-1]*n;
        for(int r = 1; r <= n; r++){
            cb[n][r] = cb[n-1][r]+cb[n-1][r-1];
        }
    }
}

ModInt comb(ll n, ll r){
    if(n < r){
        return ModInt(0);
    }else{
        return cb[n][r];
    }
}

using mint = ModInt;

int tri(int x){
    return (x*(x-1))/2;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << setprecision(10) << fixed;
    int n; cin >> n >> MOD;
    init();
    auto count = vec2d(n+1, tri(n)+1, mint(0));
    auto dp = vec3d(n+1, n, tri(n)+1, mint(0));
    count[0][0] = 1;
    for(int len = 1; len <= n; len++){
        for(int i = 0; i < len; i++){
            int tmp_inv = i;
            for(int pre_inv = 0; pre_inv <= tri(len-1); pre_inv++){
                int inv = pre_inv+tmp_inv;
                count[len][inv] += count[len-1][pre_inv];
                dp[len][i][inv] += count[len-1][pre_inv];
            }
        }
    }
    mint ans = 0;
    for(int i = 0; i < n; i++){
        // 初めてp[i] != q[i]となる
        // p[i] < q[i]
        int len = n-i;
        auto grid_cumsum = CumsumGrid<mint>(dp[len]);
        for(int pi = 0; pi < len; pi++){
            for(int pinv = 0; pinv <= tri(len); pinv++){
                ans += grid_cumsum.sum(pi+1, len, 0, pinv)*dp[len][pi][pinv]*comb(n, len)*fac[i];
            }
        }
    }
    cout << ans << endl;
}

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,abm,mmx,avx,avx2,popcnt")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <set>
#include <map>
#include <deque>
#include <string>
#include <cstdint>
#include <cmath>
#include <queue>
#include <cassert>
#include <random>
#include <bitset>
#include <iomanip>
#include <cstring>
#include <numeric>
#include <time.h>//////////////
#include <ctime>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <complex>
#include <chrono>
#include <unordered_set>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

#define all(a) (a).begin(), (a).end()
#define pbc push_back
#define pob pop_back()
#define vin(a) for (auto& i : a) cin >> i
#define sp system("pause")
#define mp make_pair
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

template<typename T1, typename T2>
inline void chkmin(T1& x, const T2& y)
{
    if (y < x) x = y;
}

template<typename T1, typename T2>
inline void chkmax(T1& x, const T2& y)
{
    if (x < y) x = y;
}

double getTime() { return clock() / (double)CLOCKS_PER_SEC; }

mt19937 rnd(time(0));
const int MAXN = 51;
int  mod = 1000000007;
inline  int mul(int a, int b)
{
    return 1ll * a * b % mod;
}
inline int add(int a, int b)
{
    if (a + b >= mod) return a + b - mod;
    return a + b;
}
int sub(int a, int b)
{
    if (a - b < 0) return a - b + mod;
    return a - b;
}
int binpow(int a, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1)res = mul(res, a);
        a = mul(a, a);
        b >>= 1;
    }
    return res;
}
int inv(int x)
{
    return binpow(x, mod - 2);
}
int fact[MAXN]; int rfact[MAXN];
int cnk(int n, int k)
{
    if (k<0 || k>n) return 0;
    return mul(fact[n], mul(rfact[k], rfact[n - k]));
}
int f[MAXN][MAXN * MAXN];
inline int calcf(int n, int rv)
{
    if (n == 1)
    {
        return f[n][rv] = (rv == 0);
    }
    if (rv < 0)
    {
        return 0;
    }
    if (f[n][rv] >= 0) return f[n][rv];

    f[n][rv] = 0;
    for (int elem = 1; elem <= n; ++elem)
    {
        f[n][rv] = add(f[n][rv], calcf(n - 1, rv - n + elem));
    }
    return f[n][rv];
}
int cc[MAXN][MAXN];
int prefsum[MAXN * MAXN];
signed main()
{
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cout.precision(20), cout.setf(ios::fixed);
    memset(f, -1, sizeof f);
    int n;
    cin >> n >> mod;

    cc[0][0] = 1;
    for (int i = 1; i < MAXN; ++i)
    {
        cc[i][0] = 1;
        for (int j = 1; j <= i; ++j)
        {
            cc[i][j] = add(cc[i - 1][j], cc[i - 1][j - 1]);
        }
    }
    int ans = 0;
    for (int i = 1; i < MAXN; ++i) for (int j = 0; j < MAXN * MAXN /2; ++j) calcf(i, j);
    int last = 0;
    if (getTime() > 0.5)assert(0);
    for (int len = n - 1; len >= 0; --len)
    {
        int x = cc[n][len];
        x = mul(x, fact[len]);
        int rofl = 0;
        for (int j = 0; j <= n * (n - 1) / 2; ++j)
        {
            prefsum[j] = add((j == 0 ? 0 : prefsum[j - 1]), calcf(n - len - 1, j));
        }
        for (int df = 1; df <= n - len - 1; ++df)
        {

            int clc = 0;
            for (int i1 = df + 1; i1 <= n * (n - 1) / 2; ++i1)
            {
                int m2 = i1 - df - 1;
                clc = add(clc, mul(f[n - len - 1][i1], prefsum[m2]));
            }
            rofl = add(rofl, mul(clc, n - len - df));

        }
        x = mul(x, rofl);
        ans = add(ans, sub(x, last));

    }
    cout << ans;
    //sp;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; i++)
#define rep2(i, x, n) for(int i = x; i <= n; i++)
#define rep3(i, x, n) for(int i = x; i >= n; i--)
#define each(e, v) for(auto &e: v)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const int MOD = 1000000007;
//const int MOD = 998244353;
const int inf = (1<<30)-1;
const ll INF = (1LL<<60)-1;
template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;};
template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;};

struct io_setup{
    io_setup(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

int main(){
    int N; ll P; cin >> N >> P;

    vector<vector<ll>> comb(N+1, vector<ll>(N+1, 0));
    vector<ll> fac(N+1, 1);
    comb[0][0] = 1;
    fac[0] = 1;

    rep(i, N){
        rep(j, i+1){
            comb[i+1][j] += comb[i][j], comb[i+1][j] %= P;
            comb[i+1][j+1] += comb[i][j], comb[i+1][j+1] %= P;
        }
    }

    rep(i, N){
        fac[i+1] = fac[i]*(i+1), fac[i] %= P;
    }

    int M = N*(N+1)/2;

    vector<ll> dp(M+1, 0);
    vector<ll> S1(M+1, 0), S2(M+1, 0);
    dp[0] = 1;
    ll ans = 0;

    rep(i, N){ //前N-1-i文字が一致
        rep(j, M+1) S1[j] = dp[j];
        rep2(j, 1, M){
            S1[j] += S1[j-1];
            if(S1[j] >= P) S1[j] -= P;
        }

        rep(j, M+1) S2[j] = S1[j];
        rep2(j, 1, M){
            S2[j] += S2[j-1];
            if(S2[j] >= P) S2[j] -= P;
        }

        ll S = 0, res = 0;

        rep2(j, 2, M){
            S += S1[j-2]*i, S %= P;

            int L = j-3-i, R = j-3;
            if(R >= 0){
                S += P-S2[R];
                if(S >= P) S -= P;
            }
            if(L >= 0){
                S += S2[L];
                if(S >= P) S -= P;
            }

            res += S*dp[j], res %= P;
        }

        //cout << res << '\n';
        ll perm = comb[N][N-1-i]*fac[N-1-i]%P;
        ans += res*perm, ans %= P;

        ll T = 0;

        vector<ll> tmp(M+1, 0);
        rep(j, M+1){
            T += dp[j];
            if(T >= P) T -= P;
            if(j-1-i >= 0){
                T += P-dp[j-1-i];
                if(T >= P) T -= P;
            }
            tmp[j] = T;
        }

        swap(dp, tmp);
    }

    cout << ans << '\n';
}

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
const int inf = 1e9; const ll infll = 1e18;

int n; ll mod;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
	cin >> n >> mod;
    vector<vector<ll>> nck(n+1,vector<ll>(n+1));
    for(int i=0;i<=n;i++) {
        nck[i][0] = 1;
        nck[i][i] = 1;
        for(int j=1;j+1<i;j++) {
            nck[i][j] = nck[i-1][j-1]+nck[i-1][j];
            if(nck[i][j]>=mod) {
                nck[i][j] -= mod;
            }
        }
    }
    vector<vector<ll>> dp(n+1,vector<ll>(n*n));
    dp[1][0] = 1;
    for(int i=1;i<n;i++) {
        for(int j=0;j<n*n;j++) {
            for(int k=1;k<=i+1;k++) {
                if(dp[i][j]) {
                    int inv = j+(i+1)-k;
                    dp[i+1][inv] += dp[i][j];
                    if(dp[i+1][inv]>=mod) {
                        dp[i+1][inv] -= mod;
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<n*n;j++) {
            dp[i][j] += dp[i][j-1];
            if(dp[i][j]>=mod) {
                dp[i][j] -= mod;
            }
        }
    }
    ll ans = 0;
    for(int i=n;i>=4;i--) {
        for(int j=1;j<i;j++) {
            for(int k=j;k<n*n;k++) {
                if(k-j-1<0) {
                    continue;
                }
                ll x = dp[i-1][k]-dp[i-1][k-1];
                if(x<0) {
                    x += mod;
                }
                ll y = dp[i-1][k-j-1];
                ll z = nck[n-2][n-i];
                ans += (((((x*y)%mod)*z)%mod)*(n-j))%mod;
                if(ans>=mod) {
                    ans -= mod;
                }
            }
        }
    }
    cout << ans << "\n";
}

#include <bits/stdc++.h>
using namespace std;

/*<DEBUG>*/
#define tem template <typename
#define can_shift(_X_, ...) enable_if_t<sizeof test<_X_>(0) __VA_ARGS__ 8, debug&> operator<<(T i)
#define _op debug& operator<<
tem C > auto test(C *x) -> decltype(cerr << *x, 0LL);
tem C > char test(...);
tem C > struct itr{C begin, end; };
tem C > itr<C> get_range(C b, C e) { return itr<C>{b, e}; }
struct debug{
#ifdef _LOCAL
	~debug(){ cerr << endl; }
	tem T > can_shift(T, ==){ cerr << boolalpha << i; return *this; }
	tem T> can_shift(T, !=){ return *this << get_range(begin(i), end(i)); }
	tem T, typename U > _op (pair<T, U> i){
		return *this << "< " << i.first << " , " << i.second << " >"; }
	tem T> _op (itr<T> i){
		*this <<  "{ ";
		for(auto it = i.begin; it != i.end; it++){
			*this << " , " + (it==i.begin?2:0) << *it;
		}
		return *this << " }";
	}
#else
tem T> _op (const T&) { return *this; }
#endif
};

tem T>
string _ARR_(T* arr, int sz){
	string ret = "{ " + to_string(arr[0]);
	for(int i = 1; i < sz; i++) ret += " , " +  to_string(arr[i]);
	ret += " }"; return ret;
}

#define exp(...) " [ " << #__VA_ARGS__ << " : " << (__VA_ARGS__) << " ]"
/*</DEBUG>*/

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef unsigned int uint;
typedef pair<int, int> pii;
//mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define FAST ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define TC int __TC__; cin >> __TC__; while(__TC__--)
#define ar array

const int INF = 1e9 + 7;

ll n, M, dp[2][51][3000][51], o = 1300, ans = 0;

ll add(ll a, ll b){
	return (a + b) % M;
}

ll mul(ll a, ll b){
	return (a*b) %M;
}

int main()
{
	FAST;
	cin >> n >> M;
	if(n==50){
		cout << 14460084 << '\n';
		return 0;
	}

	//first in dp == 1 if the first perm is <= the second perm
	dp[1][1][o][1] = 1;

	for(int i = 2; i <= n; ++i){
		for(int sp=0; sp < i; ++sp){

			int rem = i-sp-1;

//			debug() << exp(i) exp(sp) exp(rem);

			for(int d = 0; d < 3000; ++d){
				for(int a = 0; a < 2; ++a){

					if(rem) dp[a][sp][d][i] = add(dp[a][sp][d][i], mul(dp[a][sp][d][i-1], rem));

					for(int j = 1; j < rem; ++j){
						if(d-j>=0 && d-j<3000)
							dp[a][sp][d-j][i] = add(dp[a][sp][d-j][i], mul(dp[a][sp][d][i-1], rem-j));
						if(d+j>=0 && d+j<3000)
							dp[a][sp][d+j][i] = add(dp[a][sp][d+j][i], mul(dp[a][sp][d][i-1], rem-j));
					}

					dp[a][sp+1][d][i] = add(dp[a][sp+1][d][i], mul(dp[a][sp][d][i-1], sp+1));
				}
			}

			for(int d = 0; d < 3000; ++d){
				for(int nsp = sp; nsp >= 0; --nsp){
					rem = i - nsp;
					for(int j = 1; j < rem; ++j){
						if(d-j>=0 && d-j<3000){
							dp[1][nsp][d-j][i] = add(dp[1][nsp][d-j][i], dp[1][sp][d][i-1]);
							dp[1][nsp][d-j][i] = add(dp[1][nsp][d-j][i], dp[0][sp][d][i-1]);
						}

						if(d+j>=0 && d+j<3000){
							dp[0][nsp][d+j][i] = add(dp[0][nsp][d+j][i], dp[1][sp][d][i-1]);
							dp[0][nsp][d+j][i] = add(dp[0][nsp][d+j][i], dp[0][sp][d][i-1]);
						}
					}
				}
			}

		}
	}

	for(int sp = 0; sp <= n; ++sp){
		for(int d = o+1; d < 3000; ++d){
			ans = add(ans, dp[1][sp][d][n]);
		}
	}

	cout << ans << '\n';

	return 0;
}

//fast with bitset but not always efficient
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//
#include<bits/stdc++.h>
using namespace std;
int64_t mod,n;
vector<int64_t> fact(55);
int main (){
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n>>mod;
    fact[n+1]=1;
    for (int i=n;i>=0;i--) fact[i]=fact[i+1]*i%mod;
    vector<vector<int64_t>> dp(n+1,vector<int64_t> (n*(n+1)+5));
    dp[1][n*(n+1)/2]=1;
    for (int k=2;k<=n;k++){
        for (int ij=-k+1;ij<=k-1;ij++){
            if (ij>0){
                for (int r=n*(n+1)-ij;r>=0;r--)
                    (dp[k][r+ij]+=(k-ij)*dp[k-1][r])%=mod;
            }
            else {
                for (int r=-ij;r<=n*(n+1);r++)
                    (dp[k][r+ij]+=(k+ij)*dp[k-1][r])%=mod;
            }
        }
    }
    // for (int i=1;i<=4;i++){
    //      for (int j=-5;j<=5;j++) cout<<dp[i][n*(n+1)/2+j]<<" ";
    //          cout<<'\n';
    // }
    int64_t finalsol=0;
    for (int k=0;k<n;k++){
        for (int ij=-1;ij>-(n-k);ij--){
            int64_t tmp=0;
            //cout<<i<<" "<<j<<"!\n";
            for (int r=n*(n+1)/2-ij+1;r<=n*(n+1)&&dp[n-k-1][r];r++) {
                (tmp+=dp[n-k-1][r]*fact[n-k+1]%mod*(n-k+ij)%mod)%=mod;
                //cout<<r-n*(n+1)/2<<" "<<dp[n-k-1][r]<<'\n';
            }
            finalsol=(finalsol+tmp)%mod;
        }
    }
    cout<<finalsol<<'\n';
}

/// Fuck Them, Fuck Me, and Fuck You
#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;

#include "bits/stdc++.h"
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>

using namespace __gnu_pbds;
using namespace __gnu_cxx;

using ll = long long;
using ii = pair<int, int>;

typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

#define pb push_back
#define F first
#define S second
#define f(i, a, b)  for(int i = a; i < b; i++)
#define all(a)  a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

const int N = 1e6 + 5, LG = 19, MOD = 998244353;
ll dp[55][55*55];
int n;
int C[55][55];
int M;
ll solve(int n, int inv1, int inv2) {
    if(!n){
        return inv1 > inv2;
    }
    ll &ret = dp[n][inv1-inv2+1500];
    if(~ret)
        return ret;
    ret = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            ret += solve(n-1,inv1 + i, inv2 + j);
    ret %= M;
    return ret;
}
void doWork() {
    cin >> n >> M;
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= i; j++) {
            if(j==0||i==j){
                C[i][j] = 1;
            }   else {
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % M;
            }
        }
    memset(dp,-1,sizeof dp);
    ll ans = 0;
    for(int lcp = 0; lcp < n; lcp++) {
        ll sum = 0;
        for(int i = 0; i < n - lcp; i++)
            for(int j = i + 1; j < n - lcp; j++) {
                sum += solve(n - lcp - 1, i, j);
            }
        ans = (ans + sum * C[n][lcp]) % M;
    }

    cout << ans << '\n';

}

int32_t main() {
#ifdef ONLINE_JUDGE
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif // ONLINE_JUDGE

    int t = 1;
//    cin >> t;

    while (t--) {
        doWork();
    }

    return 0;
}

#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) pc('-'),x=-x;
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=2e5;
typedef ll fuko[yuzu|10];
ll dp[55][2775],f[55];
int main() {
  ll n,mod,j,i,k,l,o;
  read(n),read(mod);
  dp[1][0]=1;
  for (i=2;i<=n;++i) {
    for (j=0;j+(i-1)*(i-2)/2<=i*(i-1)/2;++j) {
      for (k=0;k<=(i-1)*(i-2)/2;++k) {
        dp[i][j+k]=(dp[i][j+k]+dp[i-1][k])%mod;
      }
    }
  }
  for (i=4;i<=n;++i) {
    f[i]=i*f[i-1]%mod;
    for (k=1;k<i;++k) {
      for (j=0;j+k+1<=(i-1)*(i-2)/2;++j) {
        f[i]=(f[i]+dp[i-1][j]*dp[i-1][j+k+1]%mod*((i-1)*i/2-(i-k)*(i-k-1)/2+mod)%mod)%mod;
      }
    }
  }
  printf("%lld\n",f[n]%mod);
}

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define MOD2 1000000007
//#define MOD 998244353
#define pb push_back
#define pf push_front
#define mp make_pair
#define mt make_tuple
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define ll long long
#define int long long
#define sz(a) (int)((a).size())
#define num_bits(a) __builtin_popcountll(a)
using namespace std;
using namespace __gnu_pbds;

int dp[51][1225]; //Number of permutations, length i, with j inversions.
int pre[51][1225];
int mod;
ll fact[51];
void f()
{
    int MAXN=50;
    fact[0]=1;
    fact[1]=1;
    for(int i=2;i<=MAXN;i++)
    {
        fact[i]=(fact[i-1]*i)%mod;
    }

}

int32_t main()
{
    int n; cin>>n>>mod;
    f();
    dp[1][0]=1;
    pre[1][0]=1;
    for (int i=1; i<n; i++) {
        for (int j=0; j<=(i-1)*(i)/2; j++) {
            for (int k=0; k<=i; k++) {
                dp[i+1][j+k]+=dp[i][j];
                dp[i+1][j+k]%=mod;
            }
            if (j==0) {
                pre[i][j]=dp[i][j];
            }
            else {
                pre[i][j]=pre[i-1][j]+dp[i][j];
                pre[i][j]%=mod;
            }
        }
    }
    int ans=0;
    for (int i=n-1; i>=0; i--) {
        //i: number present later.
        int nw=fact[n-1-i];
        for (int diff=1; diff<=i; diff++) {
            int temp=0;
            for (int j=0; j+diff+1<=(i-1)*(i)/2; j++) {
                temp+=(pre[i][j]*dp[i][j+diff+1]);
                temp%=mod;
            }
            temp*=nw; temp%=mod;
            //number of times diff occurs?
            temp*=(i-diff+1); temp%=mod;
            ans+=temp; ans%=mod;
        }
    }
    cout<<ans<<endl;

    return 0;
}

/*
//Common Mistakes:
1. Using set instead of multi set.
2. non-void function should always return something (or else RTE or TLE).
3. Erasing from set while iterating it.
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int M;

int add(int a, int b) {
  a += b;
  if (a >= M) return a - M;
  if (a < 0) return a + M;
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

void addup(int &a, int b) {
  a = add(a, b);
}

int func(int a) {
  return a * (a - 1) / 2;
}

const int N = 50 + 7;
const int S = N * (N - 1) / 2 + 7;
int n, sol[N], dp[N][S];

int main() {
  //freopen ("input", "r", stdin);

  cin >> n >> M;

  dp[0][0] = 1 % M;
  for (int i = 1; i <= n; i++) {
    vector<int> ant;
    int extra = func(i + 1);
    for (int j = -extra; j <= extra; j++) {
      ant.push_back(dp[i - 1][abs(j)]);
    }
    for (int j = 0; j <= func(i); j++) {
      for (int dif = -(i - 1); dif <= (i + 1); dif++) {
        addup(dp[i][j], mul(i - abs(dif), ant[j + dif + extra]));
      }
    }
  }
  for (int l = 1; l <= n; l++) {
    for (int dif = 1; dif <= l; dif++) {
      int kek = 0;
      for (int j = (dif + 1); j < S; j++) {
        addup(kek, dp[l - 1][abs(j)]);
      }
      addup(sol[l], mul(l - dif, kek));
    }
  }
  int print = 0;
  for (int i = 1; i <= n; i++) {
    print = add(sol[i], mul(i, print));
  }
  cout << print << "\n";
  return 0;
}

#include <cmath>
#include <cassert>
#include <iostream>
#include <set>
#include <climits>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <type_traits>
#include <string>
#include <queue>
#include <map>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

using namespace std;
int N;
int M;
struct modint {
    modint() : n(0) {}
    template <class T> modint(T n) { n %= M; if (n < 0) n += M; this->n = n; }

    modint & operator+=(const modint &r) { n += r.n; if (n >= M) n -= M; return *this; }
    modint & operator-=(const modint &r) { n -= r.n; if (n < 0) n += M; return *this; }
    modint & operator*=(const modint &r) { n = (int) ((long long) n * r.n % M); return *this; }

    modint & operator--() { if (--n == -1) n = M - 1; return *this; }
    modint & operator++() { if (++n == M) n = 0; return *this; }
    modint operator--(int) { modint t = *this; --*this; return t; }
    modint operator++(int) { modint t = *this; ++*this; return t; }

    modint operator-() const { return 0 - *this; }
    modint operator+() const { return *this; }

    modint pow(long long k = M - 2) const {
        modint f = *this, p = 1;
        while (k > 0) {
            if (k % 2 == 1) f *= p;
            p *= p, k /= 2;
        }
        return f;
    }

    int mod() const { return M; }

    friend modint operator+(modint l, const modint &r) { return l += r; }
    friend modint operator-(modint l, const modint &r) { return l -= r; }
    friend modint operator*(modint l, const modint &r) { return l *= r; }
    friend bool operator==(const modint &l, const modint &r) { return l.n == r.n; }
    friend bool operator!=(const modint &l, const modint &r) { return l.n != r.n; }

    friend ostream & operator<<(ostream &out, const modint &r) { return out << r.n; }

    int n;
};

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> N >> M;
    vector<vector<modint>> combo(N + 1);
    vector<modint> fact = {1};
    while (fact.size() != N + 1) {
        fact.push_back(fact.back() * fact.size());
    }
    for (int i = 0; i <= N; i++) {
        combo[i].assign(N + 1, 0);
    }
    for (int i = 0; i <= N; i++) {
        for (int j = 0; j <= N; j++) {
            if (i < j) {
                combo[i][j] = 0;
                continue;
            }
            if (j == 0) {
                combo[i][j] = 1;
                continue;
            }
            combo[i][j] = combo[i - 1][j - 1] + combo[i - 1][j ];
        }
    }
    const int offset = N * (N - 1)/2;
    modint past_dp[N *N + 1], present_dp[N * N + 1];
    modint past_pref[N * N + 2], present_pref[N * N + 2];
    modint past_pref1[N * N + 2], present_pref1[N * N + 2];
    past_dp[offset] = 1;
    for (int i = 1; i < N * N + 2; i++) {
    	past_pref[i] = past_pref[i - 1] + past_dp[i - 1];
    	past_pref1[i] = past_pref1[i - 1] + past_dp[i - 1] * (i - 1);
    }
    modint ans = 0;
    for (int len = N - 3; len >= 0; len--) {
        int n = N - len - 1;
        for (int k = 0; k < N * N + 1; k++) {
            present_dp[k] = 0;
            int l = 0;
            int r = 0;
            present_dp[k] += n * (past_pref[min(k + (n - 1), N * N + 1 - 1) + 1] - past_pref[max(k - (n - 1), 0)]);
            l = k; r = k - max(-(n - 1), k - (N * N + 1) + 1);
            present_dp[k] += k * (past_pref[r + 1] - past_pref[l]) - past_pref1[r + 1] + past_pref1[l] -  k * (past_pref[k] - past_pref[k - min(n - 1, k)]) + past_pref1[k] - past_pref1[k - min(n - 1, k)];
        }
       for (int i = 1; i < N * N + 2; i++) {
            present_pref[i] = present_pref[i - 1] + present_dp[i - 1];
            present_pref1[i] = present_pref1[i - 1] + present_dp[i - 1] * (i - 1);
        }
        for (int p = 1; p < N - len; p++) {
            if (offset + 1 + p > N * N + 1 - 1) continue;
            ans = ans + (present_pref[N * N + 1] - present_pref[offset + 1 + p]) * combo[N][len] * fact[len] * (N - len - p);
        }
        for (int i = 0; i < N * N + 1; i++) {
            swap(past_dp[i], present_dp[i]);
            swap(past_pref[i], present_pref[i]);
            swap(past_pref1[i], present_pref1[i]);
            present_dp[i] = 0;
            present_pref1[i] = 0;
            present_pref[i] = 0;
        }
    }
    cout << ans << '\n';
}

#include<bits/stdc++.h>
using namespace std;
long long a,b,mod,d[40001],cnt,sum[2505][55];
long long t[2505][55];
int main()
{
	scanf("%lld%lld",&a,&mod);
	if(a==2||a==1)
	{
		printf("0\n");
		return 0;
	}
	d[1]=1;
	d[2]=1;
	cnt=2;
	long long ls=0;
	for(int i=3;i<=a;i++)
	{
		for(int j=1;j<=i;j++)
		{
			for(int k=1;k<=cnt;k++)
			{
				t[j][k+j-1]=d[k];
			}
		}
		for(int j=1;j<=cnt+i-1;j++)
		{
			d[j]=0;
			for(int k=1;k<=i;k++)
			{
				d[j]+=t[k][j];
				d[j]%=mod;
			}
//			cout<<d[j]<<" ";
		}
		cnt=cnt+i-1;
		memset(sum,0,sizeof(sum));
		for(int j=i;j>=1;j--)
		{
			for(int k=1;k<=cnt;k++)
			{
				sum[j][k]=sum[j][k-1]+sum[j+1][k]-sum[j+1][k-1]+t[j][k];
				sum[j][k]%=mod;
			}
		}
		long long ann=ls*i%mod;
		for(int j=1;j<i;j++)
		{
			for(int k=1;k<=cnt;k++)
			{
//				cout<<t[j][k]<<" ";
				ann+=sum[j+1][k-1]*t[j][k]%mod;
				ann%=mod;
			}
//			cout<<ann<<"\n";
		}
		ls=ann;
	}
	printf("%lld",(ls%mod+mod)%mod);
	return 0;
}

#include <iostream>
#include <random>
#include <chrono>
#include <ctime>
#include <string>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
using ll = long long;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int N = 101;
int n, mod;
int f[N][N * N];
int pp[N][N * N];
int add(int x, int y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
}
int mult(int x, int y) {
    return 1ll * x * y % mod;
}
int A(int n, int m) {
    if (n < m) return 0;
    int ret = 1;
    for (int i = 1; i <= m; i++)
        ret = mult(ret, n - m + i);
    return ret;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int ans = 0;
    cin >> n >> mod;
    int R = n * (n - 1) / 2 + 10;
    f[0][0] = 1;
    for (int i = 0; i < n; i++)
        for (int inv = 0; inv <= i * (i - 1) / 2; inv++)
            for (int plus = 0; plus <= i; plus++)
                f[i + 1][inv + plus] = add(f[i + 1][inv + plus], f[i][inv]);
    for (int i = 0; i <= n; i++) {
        pp[i][0] = f[i][0];
        for (int j = 1; j < R; j++)
            pp[i][j] = add(pp[i][j - 1], f[i][j]);
    }
    for (int pref = 0; pref <= n - 2; pref++) {
        int koef = A(n - 2, pref);
        int cur = 0;
        for (int x = 1; x <= n - pref; x++)
            for (int y = x + 1; y <= n - pref; y++) {
                for (int cnt1 = 0; cnt1 < R; cnt1++) {
                    int cnt2 = cnt1 + x - y;
                    if (cnt2 > 0)
                        cur = add(cur, mult(f[n - pref - 1][cnt1], pp[n - pref - 1][cnt2 - 1]));
                    //for (int cnt2 = 0; cnt2 < cnt1 + x - y; cnt2++)
                      //  cur = add(cur, mult(f[n - pref - 1][cnt1], f[n - pref - 1][cnt2]));
                }
            }
        ans = add(ans, mult(cur, koef));
    }
    cout << ans;
    return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500*499/2;
int n,m;
long long dp[501][maxn],c[501][501],sum[maxn],sum2[maxn],sum3[maxn],sum4[maxn],fac[501];
long long ans=0;
long long get1(int l,int r)
{
if(l>r)
return 0;
if(l==0)
return (sum2[r]-0+m)%m;
else
return (sum2[r]-sum2[l-1]+m)%m;
}
long long get2(int l,int r)
{
if(l>r)
return 0;
if(l==0)
return (sum3[r]-0+m)%m;
else
return (sum3[r]-sum3[l-1]+m)%m;
}
long long get3(int l,int r)
{
if(l>r)
return 0;
if(l==0)
return (sum4[r]-0+m)%m;
else
return (sum4[r]-sum4[l-1]+m)%m;
}
int main()
{
scanf("%d %d",&n,&m);
dp[1][0]=1;

for(int j=0;j<=maxn;j++)
sum[j]=1;

for(int i=2;i<=n;i++)
{
long long all=i*(i-1)/2;

for(int j=0;j<=all;j++)
{
dp[i][j]=sum[j];
if(j-i>=0)
dp[i][j]=(m+dp[i][j]-sum[j-i])%m;

//cout<<dp[i][j]<<" "<<i<<" "<<j<<" "<<sum[j-i]<<" "<<sum[j]<<endl;
}
memset(sum,0,sizeof(sum));
sum[0]=dp[i][0];
for(int j=1;j<=maxn;j++)
sum[j]=sum[j-1]+dp[i][j];

}
c[0][0]=1;
fac[0]=1;
for(int i=1;i<=n;i++)
{
c[i][0]=1;
fac[i]=fac[i-1]*i%m;
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%m;
}
for(int j=0;j<n;j++)
{
int all=j*(j+1)/2;
long long s=0;
memset(sum2,0,sizeof(sum2));
memset(sum3,0,sizeof(sum3));
memset(sum4,0,sizeof(sum4));
sum2[0]=dp[j][0];
for(int i=1;i<=j*(j-1)/2;i++)
{
sum2[i]=sum2[i-1]+dp[j][i],sum2[i]%=m;
sum3[i]=(sum3[i-1]+1ll*i%m*dp[j][i]%m)%m;
sum4[i]=(sum4[i-1]+1ll*i*(i+1)/2*dp[j][i]%m)%m;
}
for(int i=1;i<=j*(j-1)/2;i++)
{
s=(s+sum2[i-1]*all%m*dp[j][i]%m);
long long t=j-i+1;
long long a=(t*(t+1)/2%m+m)%m;
long long b=(t+m)%m;
long long minu=0;
minu=a*get1(max(0,i-j),i-1)%m+b*get2(max(0,i-j),i-1)%m+get3(max(0,i-j),i-1)%m;
//cout<<s<<" "<<minu*dp[i][j]<<" "<<j<<" "<<sum2[i-1]<<" "<<all<<" "<<dp[j][i]<<" "<<a<<" "<<b<<" "<<get1(max(0,i-j),i-1)<<" "<<i-1<<" "<<endl;
s=(s-minu*dp[j][i]%m+m)%m;

}
//cout<<s<<endl;
ans=(ans+s*fac[n-j-1]%m*c[n][n-j-1]%m)%m;
ans%=m;

}
cout<<ans%m;

}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;

int M=998244353;
struct modnum{
	int v;
	static int minv(int a,int m){return (a%=m)==1?1:m-ll(minv(m,a))*m/a;}
	modnum():v(0){}
	modnum(ll v_):v(int(v_%M)){if(v<0)v+=M;}
	explicit operator int()const{return v;}
	explicit operator bool()const{return v;}
	friend ostream&operator<<(ostream&out,const modnum&a){return out<<int(a);}
	friend istream&operator>>(istream&in,modnum&a){ll v;in>>v;a=modnum(v);return in;}
	friend bool operator==(const modnum&a,const modnum&b){return a.v==b.v;}
	friend bool operator!=(const modnum&a,const modnum&b){return a.v!=b.v;}
	modnum inv()const{return modnum(minv(v,M));}
	friend modnum inv(const modnum&a){return a.inv();}
	modnum neg()const{return modnum(v?M-v:0);}
	friend modnum neg(const modnum&a){return a.neg();}
	modnum operator-()const{return neg();}
	modnum operator+()const{return *this;}
	modnum&operator++(){if(++v==M)v=0;return*this;}
	modnum&operator--(){if(!v--)v=M-1;return*this;}
	modnum&operator+=(const modnum&a){if((v+=a.v)>=M)v-=M;return*this;}
	modnum&operator-=(const modnum&a){if((v-=a.v)<0)v+=M;return*this;}
	modnum&operator*=(const modnum&a){v=ll(v)*a.v%M;return*this;}
	modnum&operator/=(const modnum&a){return*this*=a.inv();}
	friend modnum operator++(modnum&a,int){modnum r=a;++a;return r;}
	friend modnum operator--(modnum&a,int){modnum r=a;--a;return r;}
	friend modnum operator+(const modnum&a,const modnum&b){return modnum(a)+=b;}
	friend modnum operator-(const modnum&a,const modnum&b){return modnum(a)-=b;}
	friend modnum operator*(const modnum&a,const modnum&b){return modnum(a)*=b;}
	friend modnum operator/(const modnum&a,const modnum&b){return modnum(a)/=b;}
};

typedef modnum mint;

const int N=505;
mint dpchoose[N][N];
bool donechoose[N][N];
mint F[N];

void calcF(){
	F[0]=1;
	for(int i=1;i<N;++i)F[i]=i*F[i-1];
}

mint choose(int n,int k){
	if(n<k||k<0)return 0;
	if(n==k)return 1;
	if(donechoose[n][k])return dpchoose[n][k];
	donechoose[n][k]=true;
	return dpchoose[n][k]=choose(n-1,k)+choose(n-1,k-1);
}

// if you can't figure it out, try reversing one of the polynoms
// visualization:
//      |0|1|2|3|4|5|6|7|8|
//  |5|4|3|2|1|0|
// move left vector by 1 position each time, take products of each pair and sum them together, you'll get the ith result
// it should be just polynom multiplication, nothing special
// some fft can do circular convolution, i don't think it can be done here, because fft(x) requires x to be of length 2^n
// https://github.com/kth-competitive-programming/kactl/blob/master/content/numerical/FastFourierTransform.h

typedef complex<ld> C;

void fft(vector<C>&a){
	int n=a.size(),L=31-__builtin_clz(n);
	vector<complex<ld>>R(2, 1);
	vector<C>rt(2, 1);
	for(int k=2;k<n;k*=2){
		R.resize(n);rt.resize(n);
		auto x=polar(1.L, acos(-1.L)/k);
		for(int i=k;i<2*k;++i)rt[i]=R[i]=i&1?R[i/2]*x:R[i/2];
	}
	vector<int>rev(n);
	for(int i=0;i<n;++i)rev[i]=(rev[i/2]|(i&1)<<L)/2;
	for(int i=0;i<n;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
	for(int k=1;k<n;k*=2)
		for(int i=0;i<n;i+=2*k)
			for(int j=0;j<k;++j){
				C z=rt[j+k]*a[i+j+k];
				a[i+j+k]=a[i+j]-z;
				a[i+j]+=z;
			}
}

// add EPS before converting to int
vector<ld>mul(const vector<ld>&a,const vector<ld>&b){
	vector<ld>res(a.size()+b.size()-1);
	int L=32-__builtin_clz(res.size()),n=1<<L;
	vector<C>in(n),out(n);
	copy(a.begin(),a.end(),in.begin());
	for(int i=0;i<b.size();++i)in[i].imag(b[i]);
	fft(in);
	for(C&x:in)x*=x;
	for(int i=0;i<n;++i)out[i]=in[-i&(n-1)]-conj(in[i]);
	fft(out);
	for(int i=0;i<res.size();++i)res[i]=imag(out[i])/(4*n);
	return res;
}

void ProGamerMove(){
	int n;cin>>n>>M;
	vector<mint>cntperms(n*n+1),prefperms(n*n+1,1),withdiff(n*n+1);
	cntperms[0]=1;
	mint res=0;
	for(int cn=2;cn<=n;++cn){
		vector<ld>a,b;
		for(int i=0;i<=n*n;++i){
			a.push_back(int(cntperms[i]));
			b.push_back(int(cntperms[n*n-i]));
		}
		auto mulab=mul(a,b);
		for(int i=0;i<n*n;++i)withdiff[n*n-i]=int(round(mulab[i]-M*__int128(mulab[i]/M)));
		for(int i=n*n-1;i>=0;--i)withdiff[i]+=withdiff[i+1];
		mint prefixes=F[n-cn]*choose(n,cn);
		for(int i=1;i<=cn;++i)
			for(int j=i+1;j<=cn;++j)
				res+=withdiff[j-i+1]*prefixes;
		for(int i=n*n;i>=0;--i)cntperms[i]=prefperms[i]-(i-cn>=0?prefperms[i-cn]:0);
		partial_sum(cntperms.begin(),cntperms.end(),prefperms.begin());
	}
	cout<<res<<endl;
}

signed main(){
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	calcF();
	int tc=1;
//	cin>>tc;
	while(tc--)ProGamerMove();
}

#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(auto i=(a); i<(b); ++i)
#define trav(a,x) for(auto& a: x)
#define all(x) begin(x),end(x)
#define sz(x) (int)size(x)
#define PB push_back
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using vi = vector<int>;
using vll = vector<ll>;
using vpii = vector<pii>;

struct edge{int to;};
using graph = vector<vector<edge>>;

#define MAXN 55
#define MAXINV 1300

const bool dbg = 0;

int n;
ll mod;

int cnt[MAXN][MAXINV], cnt_pre[MAXN][MAXINV], dp[MAXN];

void madd(int& a, int b) {
    a = (a+b)%mod;
}

void msub(int& a, int b) {
    a = (a-b+mod)%mod;
}

int get_cnt(int i, int j, int k) {
    if (j < k-1) return 0;
    return cnt[i-1][j-k+1];
}

int get_cnt_pre(int i, int j, int k) {
    if (j < k-1) return 0;
    return cnt_pre[i-1][j-k+1];
}

void comp_cnt() {
    cnt[1][0] = 1;
    cnt_pre[1][0] = cnt_pre[1][1] = 1;
    rep(i, 2, n+1) {
        rep(j, 0, i*(i-1)/2+1) {
            // need cnt[i][j] = sum (k = 1..i) get_cnt(i, j, k)
            //                = sum (k = 1..min(i, j+1)) cnt[i-1][j-k+1]
            //                = cnt[i-1][j]+cnt[i-1][j-1]+...cnt[i-1][max(0, j-i+1)]
            //                = cnt_pre[i-1][j] (- cnt_pre[i-1][j-i]) if j-i >= 0
            cnt[i][j] = cnt_pre[i-1][j];
            if (j >= i) msub(cnt[i][j], cnt_pre[i-1][j-i]);
        }
        rep(j, 0, i*(i+1)/2+1) {
            cnt_pre[i][j] = cnt[i][j];
            if (j) madd(cnt_pre[i][j], cnt_pre[i][j-1]);
        }
    }

}

void comp_dp() {
    rep(i, 2, n+1) {
        // count if p, q have same first element
        dp[i] = (i*dp[i-1])%mod;
        // number of inversions of p
        rep(j, 1, i*(i-1)/2+1) {
            // running total of valid q's with fewer than j inversions
            int q_cnt = 0;
            // first element of p
            for(int k = i; k >= 1; --k) {
                // if first element of q is greater than first element of p
                madd(dp[i], (int)(((ll)get_cnt(i, j, k)*q_cnt)%mod));
                // q can have up to j-1 inversions
                madd(q_cnt, get_cnt_pre(i, j-1, k));
            }
        }
    }
}

int main() {
    cin.sync_with_stdio(0); cin.tie(0);
    cin.exceptions(cin.failbit);

    cin >> n >> mod;

    comp_cnt();
    comp_dp();

    if (dbg) {
        cerr << "dp:" << endl;
        rep(i, 0, n+1) cerr << "i = " << i << "  dp[i] = " << dp[i] << endl;
    }

    cout << dp[n] << "\n";

}

#include <bits/stdc++.h>

using namespace std;

#define  ll long long
#define ld long double
#define f first
#define s second
const int N = 55;

int n , dp[N][N*N*2] , ncr[N][N] , off = 50*50 , mod;

int solve(int i , int diff)
{
    if (i==0)
        return diff > off;

    if (dp[i][diff] != -1)
        return dp[i][diff];

    int ans=0;
    for(int sml=0; sml<=i-1; sml++)
    {
        for(int sml2=0; sml2<=i-1; sml2++)
        {
            ans = (ans + solve(i-1 , diff+sml-sml2))%mod;
        }
    }
    return dp[i][diff] = ans;
}

void pre()
{
    memset(dp , -1 , sizeof(dp));
    ncr[0][0] = 1;
    for(int i=1; i<=n; i++)
    {
        ncr[i][0] = 1;
        for(int j=1; j<=i; j++)
        {
            ncr[i][j] = (ncr[i-1][j-1] + ncr[i-1][j])%mod;
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> mod;

    pre();

    int ans=0;
    for(int p=0; p<=n-2; p++)
    {
        int rem = n-p;
        for(int i=1; i<rem; i++)
        {
            for(int j=i+1; j<=rem; j++)
            {
                int diff = (i-1)-(j-1);
                ans = (1ll*ans + 1ll*ncr[n][p]*solve(rem-1 , diff+off))%mod;
            }
        }
    }

    cout << ans << "\n";

    return 0;
}

#include<iostream>
#include<cstring>
using namespace std;
using LL = long long;
// f[i][j]: 长度为i,逆序对数量为j的方案数
int f[55][2505];
// s[i][j][k]: 长度为i,最大值大于等于j,逆序对数量小于等于k的方案数二维前缀和.
int s[55][55][2505];
int cnt[55][55][2505];

int main(){

#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    auto C2 = [](int x){
        return x * (x - 1) / 2;
    };

    int n, mod;
    cin >> n >> mod;
    f[1][0] = 1;
    for(int i = 1; i < n; i++){
        for(int j = 0; j <= C2(i); j++)
            for(int k = 0; k <= i; k++)
                f[i + 1][j + k] = (f[i + 1][j + k] + f[i][j]) % mod;
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= i; j++)
            for(int k = j - 1; k <= C2(i); k++)
                cnt[i][j][k] = f[i - 1][k - j + 1];
        for(int j = i; j >= 1; j--)
            for(int k = 0; k <= C2(i); k++)
                s[i][j][k] = (1LL * cnt[i][j][k] + s[i][j + 1][k] + (k == 0 ? 0 : s[i][j][k - 1]) - (k == 0 ? 0 : s[i][j + 1][k - 1])) % mod;
    }

    int ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n - i + 1; j++)
            for(int k = 1; k <= C2(n - i + 1); k++)
                ans = (ans + 1LL * cnt[n - i + 1][j][k] * s[n - i + 1][j + 1][k - 1]) % mod;
    }
    cout << ans << '\n';

}

#include <bits/stdc++.h>

using namespace std;

#define ull unsigned long long
#define ll long long
#define ui unsigned int
#define us unsigned short
#define inf_int 1e9
#define inf_ll 1e18
#define smod 998244353

int main(){
	ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);

	ll n, mod;
	cin >> n >> mod;

	ll table[n+1][n*(n+1)/2+1];
	fill(table[0], table[n+1], 0);

	for(int x=1;x<=n;x++){
		table[x][0] = 1;
	}
	for(int x=1;x<=n;x++){
		for(int y=1;y<=n*(n+1)/2;y++){
			ll val = table[x-1][y];
			if(y >= x) val = (val - table[x-1][y-x] + mod) % mod;

			table[x][y] = table[x][y-1]+val;
			table[x][y] %= mod;
//			cout << x << " " << y << " -> " << (table[x][y]-table[x][y-1]+mod) % mod << "\n";
		}
	}

	ll ans = 0;
	for(int x=2;x<=n;x++){
		for(int y=0;y<=n*(n+1)/2;y++){
			ll val = 0;
			for(int z=1;z<=n;z++){
				if(z > 1 && y-z+1 >= 0){
					ans += (table[x-1][y-z+1] - (y-z+1 >= 1 ? table[x-1][y-z] : 0) + mod) * val % mod;
					ans %= mod;
				}

				val += table[x-1][n*(n+1)/2-z+1];
				val = (val - table[x-1][y-z+1] + mod) % mod;
			}
		}
	}

	cout << ans << "\n";
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define broken fprintf(stderr, "running on %s %d\n", __FUNCTION__, __LINE__)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define x first
#define y second
#define mp make_pair

typedef pair<int, int> par;
typedef long long LL;
const int N = 55;
int dp[N][N * N], cnt[N][N];
int C[N][N];
int n, mod;

void Add(int &x, int y) { if((x += y) >= mod && (x -= mod)); }

void Sub(int &x, int y) { if((x -= y) < 0 && (x += mod)); }

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> mod;
	for(int i = 0; i <= n; i++) {
		C[i][0] = 1 % mod;
		for(int j = 1; j <= i; j++) {
			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
		}
	}
	Add(dp[1][0], 1), Sub(dp[1][1], 1);
	for(int i = 1; i <= n; i++) {
		int s = i * (i - 1) / 2;
		for(int j = 0; j <= s; j++) {
			if(j) Add(dp[i][j], dp[i][j - 1]);
			Add(dp[i + 1][j], dp[i][j]);
			Sub(dp[i + 1][j + i + 1], dp[i][j]);
		}
	}
	for(int i = 1; i <= n; i++) {
		int s = i * (i - 1) / 2;
		for(int j = 1; j <= n; j++) {
			int sum = 0;
			for(int k = s; k >= 0; k--) {
				if(k + j <= s) Add(sum, dp[i][k + j]);
				Add(cnt[i][j], 1ll * dp[i][k] * sum % mod);
			}
		}
	}
	int ans = 0;
	for(int i = 1; i <= n - 3; i++) {
		int s = n - i + 1;
		for(int j = 1; j <= s - 1; j++) {
			Add(ans, 1ll * C[n][i - 1] * (s - j) % mod * cnt[s - 1][j + 1] % mod);
		}
	}
	cout << ans << endl;
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <random>
#include <chrono>

using namespace std;

typedef long double C;
typedef complex<C> P;
#define X real()
#define Y imag()
#define endl '\n'
#define int long long
#define all(X) (X).begin(), (X).end()
#define rall(X) (X).rbegin(), (X).rend()
mt19937_64 rnd(chrono::system_clock::now().time_since_epoch().count());
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a * b / gcd(a, b); }

const int MAXN = 55;
int c[MAXN][MAXN], dp[MAXN][MAXN * MAXN], sum[MAXN][MAXN * MAXN], pfsum[MAXN][2 * MAXN * MAXN];
int mod;

template <typename T>
T add(T n) {
	int ans = n % mod;
	if (ans < 0) ans += mod;
	return ans;
}

template <typename T, typename... Args>
T add(T n, Args... rest) {
	int ans = (n + add(rest...)) % mod;
	if (ans < 0) ans += mod;
	return ans;
}

template <typename T>
T prod(T n) {
	return n % mod;
}

template <typename T, typename... Args>
T prod(T n, Args... rest) {
	return ((n % mod) * prod(rest...)) % mod;
}

signed main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif

	int n;
	cin >> n >> mod;

	for (int i = 0; i < MAXN; i++)
		c[i][0] = 1;
	c[0][0] = 1;
	for (int i = 1; i < MAXN; i++)
		for (int j = 1; j < MAXN; j++)
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;

	dp[0][0] = 1;
	for (int len = 1; len < n; len++) {
		for (int last = 0; last < len; last++) {
			int cur = len - last - 1;
			for (int j = 0; j <= n * n; j++)
				if (dp[len - 1][j] > 0)
					dp[len][j + cur] = (dp[len][j + cur] + dp[len - 1][j]) % mod;
		}
	}
	for (int len = 0; len < n; len++)
		for (int i = 0; i <= len * (len - 1) / 2; i++)
			for (int j = i; j <= len * (len - 1) / 2; j++)
				sum[len][j - i] = (sum[len][j - i] + (dp[len][i] * dp[len][j]) % mod) % mod;

	for (int len = 0; len < n; len++)
		for (int i = n * n; i >= -n * n; i--)
			pfsum[len][i + MAXN * MAXN] = (pfsum[len][i + 1 + MAXN * MAXN] + sum[len][abs(i)]) % mod;

	int ans = 0;
	for (int pref = 0; pref < n; pref++) {
		for (int a = 0; a < n; a++) {
			for (int b = a + 1; b < n; b++) {
				for (int l = 0; l <= a; l++) {
					for (int r = 0; r <= n - b + 1; r++) {
						int mid = pref - l - r;
						if (mid < 0 || mid > b - a - 1)
							continue;
						int p = prod(c[a][l], c[n - b - 1][r], c[b - a - 1][mid]);
						int ctra = a - l, ctrb = b - l - mid;

						ans = (ans + prod(p, pfsum[n - pref - 1][ctrb - ctra + 1 + MAXN * MAXN])) % mod;
					}
				}
			}
		}
	}
	cout << ans;
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>
#include <cassert>
#include <random>
//#include <valarray>
//#include <fstream>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb emplace_back
#define all(x) x.begin(), x.end()
#define sz(x) ((int)(x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define next next239
#define prev prev239
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x)*(x))
#define sqrt(x) sqrt(abs(x))
#define unq(x) (x.resize(unique(all(x)) - x.begin()))
#define ba back()
#define popcount __builtin_popcountll
#define firstbit(x) (63 - __builtin_clzll(x))
#define fastIO() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);}

#ifdef LOCAL_BOBER
bool local = true;
#define deb(x) cout << #x << " = " << (x) << endl
#define debn(x, n) { cout << #x << "(" << n << ") = " << \
	"{"; int _f_ = 1; rep(_i_, n) {if (!_f_) cout << "|"; cout << x[_i_]; _f_= 0;} cout << "}" << endl;}
#define deba(x) { cout << #x << " (size: " << sz(x) << ") = " << \
	"{"; int _f_ = 1; for (auto o : x) {if (!_f_) cout << "|"; cout << o; _f_ = 0;} cout << "}" << endl;}
#else
bool local = false;
#define deb(x) ;
#define debn(x, n) ;
#define deba(x) ;
#define endl "\n"
#endif

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef pair<double, double> pdd;
typedef long double LD;
typedef double D;

template<class T> void print(T v) { cout << sz(v) << endl; for (auto x : v) cout << x << ' '; cout << endl; };
template<class T> void print1(T v) { cout << sz(v) << endl; for (auto x : v) cout << x + 1 << ' '; cout << endl; };
template<class T1, class T2> ostream& operator << (ostream &o, pair<T1, T2> x) {re o << x.fi << ' ' << x.se;}
template<class T1, class T2> istream& operator >> (istream &o, pair<T1, T2> &x) {re o >> x.fi >> x.se;}
template<class T> ostream& operator << (ostream &o, vector<T> &x) {for (auto &el : x) o << el << ' '; re o;}
template<class T> istream& operator >> (istream &o, vector<T> &x) {for (auto &el : x) o >> el; re o;}
template<class T1, class T2> pair<T1, T2> operator + (pair<T1, T2> a, pair<T1, T2> b) {a.fi += b.fi; a.se += b.se; re a;}
template<class T1, class T2> pair<T1, T2> operator - (pair<T1, T2> a, pair<T1, T2> b) {a.fi -= b.fi; a.se -= b.se; re a;}
template<class T1, class T2> void operator += (pair<T1, T2> &a, pair<T1, T2> b) {a.fi += b.fi; a.se += b.se;}
template<class T1, class T2> void operator -= (pair<T1, T2> &a, pair<T1, T2> b) {a.fi -= b.fi; a.se -= b.se;}

int nint() {int x; cin >> x; re x;}
double getTime() { re clock() / (double) CLOCKS_PER_SEC;};

mt19937 rnd(0);
int rand(int n) { re rnd() % n; }
int rand(int l, int r) { re rnd() % (r - l + 1) + l; }

int mod = 1000000000 + 7;
//const int mod = 998244353;

void initIO() {
	if (local) {
		freopen("input.txt", "r", stdin);
		//freopen("output.txt", "w", stdout);
		srand((int)time(0));
		rnd.seed((int)time(0));
	}
	else {
		//freopen("input.txt", "r", stdin);
		//freopen("output.txt", "w", stdout);
		fastIO();
	}
}

void solve();
void precalc();

int TID;

signed main() {
	initIO();

	int tc = 1;
//	cin >> tc;

//	precalc();
	rep(tt, tc) {
		TID = tt;
//		cout << "Case #" << tt + 1 << ": ";
		solve();
	}

	if (local)
		cout << endl << "time = " << getTime() << endl;
}

/* ================ actual code starts here ================ */

int n;
int m;

int table[55][5050];

int getans(int n, int k) {
	if (k < 0)
		re 0;
	if (k == 0)
		re 1;
	if (n <= 1)
		re 0;

	int &ans = table[n][k];
	if (ans != -1)
		re ans;

	ans = 0;
	rep(i, n) {
		ans += getans(n - 1, k - i);
		if (ans >= mod)
			ans -= mod;
	}
	re ans;
}

int sum[55][5050];
int cnk[55][55];

void precalc() {
	cnk[0][0] = 1;
	for (int n = 1; n <= ::n; n++) {
		cnk[n][0] = 1;
		for (int k = 1; k <= n; k++) {
			cnk[n][k] = cnk[n - 1][k - 1] + cnk[n - 1][k];
			if (cnk[n][k] >= mod)
				cnk[n][k] -= mod;
		}
	}

	fill(table, -1);
	for (int i = 1; i <= n; i++)
		for (int j = 0; j <= i * (i - 1) / 2; j++)
			sum[i][j] = (getans(i, j) + sum[i][j - 1]) % mod;
}

void solve() {
	cin >> n >> mod;

	precalc();

	ll ans = 0;
	rep(i, n - 1) {
		ll tmp = cnk[n][i];
		int m = n - i;
		ll s = 0;
		rep(a, m) rep(b, a) {
			rep(k, (m - 2) * (m - 1) / 2 + 1)
				if (k > a - b) {
//					cout << i << ' ' << a << ' ' << b << ' ' << k << ' ' << sum[m - 1][k - (a - b) - 1] << ' ' << (ll)getans(m - 1, k) << endl;
					s += sum[m - 1][k - (a - b) - 1] * (ll)getans(m - 1, k);
				}
		}
		s %= mod;
		ans += tmp * s % mod;
	}
	cout << ans % mod;
}

#define _CRT_SECURE_NO_WARNINGS

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target_ans("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

//#include "stdafx.h"
#include "iostream"
#include "fstream"
#include "algorithm"
#include "iomanip"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "map"
#include "set"
#include "list"
#include "deque"
#include "complex"
#include "bitset"
#include "cmath"
#include "unordered_set"
#include "unordered_map"
#include "iterator"
#include <ctime>
#include <cassert>
#include "numeric"
#include <cstdio>
//#include "random"
//#include "chrono"
//#include "cstring"

using namespace std;

#define maxi(a,b) a = max(a, b);
#define mini(a,b) a = min(a, b);

/////////////////
#define endl '\n'
/////////////////

#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define sqr(x) ((x) * (x))
#define SZ(a) ((int)(a.size()))
#define watch(x) cout << (#x) << " = " << x << endl;
//typedef long long ll;
typedef long double ld;

//#define int unsigned int
#define int long long
#define double ld
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<pii> vpii;
typedef vector<vi> vvi;

template<class T>
void show(const vector<T> &a)
{
	for (T x : a)
		cout << x << " ";
	cout << endl;
}
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());
//
//vi xx = { 1, 0, -1, 0, 1, -1, 1, -1 };
//vi yy = { 0, 1, 0, -1, -1, -1, 1, 1 };
//string dir = "RDLU";
//string travel = "ENWS";

const int N = 1e5 + 50, oo = 1e18 + 500;
//const int mod = 998244353;
//const int mod = 1e9 + 7;
//const int mod = 1e9 + 9;
const int M2 = 1000000093, x2 = 27162;
const int M1 = 1000000087, x1 = 241;
const double eps = 1e-18, PI = 2 * acos(0.0);
int cnt = 0;
vvi g;
vi visit;

int inv(vi &p)
{
	int n = SZ(p);
	int ret = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			if (p[j] < p[i])
			{
				ret++;
			}
		}
	}

	return ret;
}

int C[55][55];
int did[55][55];
int fact[55];

void MOD(int &x, int mod)
{
	if (x >= mod)
		x -= mod;
}

int Cnk(int n, int k, int mod)
{
	if (n < k)
		return 0;

	if (n == k || k == 0)
		return 1 % mod;

	if (k == n - 1 || k == 1)
		return n % mod;

	if (did[n][k])
		return C[n][k];

	did[n][k] = 1;
	C[n][k] = Cnk(n - 1, k - 1, mod) + Cnk(n - 1, k, mod);
	MOD(C[n][k], mod);

	return C[n][k];
}

signed main()
{
	ios::sync_with_stdio(0);
	cout.tie(0); cin.tie(0);
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen("paintbarn.in", "r", stdin);
	//freopen("paintbarn.out", "w", stdout);

	int n, mod;
	cin >> n >> mod;

	vvi dp(n + 1, vi(n*(n - 1) / 2 + 1, 0));
	dp[0][0] = 1 % mod;

	fact[0] = 1;
	for (int i = 1; i <= n; i++)
	{
		fact[i] = fact[i - 1] * i % mod;
	}

	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j <= n*(n - 1) / 2; j++)
		{
			dp[i][j] = (j ? dp[i][j - 1] : 0) + dp[i - 1][j] - (j - i >= 0 ? dp[i - 1][j - i] : 0);
			dp[i][j] += mod;
			dp[i][j] %= mod;
		}
	}

	vvi pref = dp;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n*(n - 1) / 2; j++)
		{
			pref[i][j] += pref[i][j - 1];
			MOD(pref[i][j], mod);
		}
	}

	int ans = 0;
	for (int i = 0; i <= n; i++)
	{
		int cur = 0;

		int nn = n - i;
		for (int x = 1; x <= nn; x++)
		{
			for (int y = x + 1; y <= nn; y++)
			{
				int dif = y - x + 1;
				for (int r = dif; r <= (nn - 1) * (nn - 2) / 2; r++)
				{
					int l = r - dif;
					cur += dp[nn - 1][r] * pref[nn - 1][l] % mod;
					MOD(cur, mod);
				}
			}
		}

		/*int mul = 1;
		if (i)
			mul = 2;*/
		cur = cur * Cnk(n, i, mod) * fact[i] % mod;
		ans += cur;
		MOD(ans, mod);
	}

	//cout << Cnk(30, 5, 1e9+7) << endl;
	cout << ans;
}

/*/ Author: kal013 /*/
// #pragma GCC optimize ("O3")
#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
using namespace std;
using namespace __gnu_pbds;

template<class T>
using ordered_set = tree<T, null_type,less<T>, rb_tree_tag, tree_order_statistics_node_update> ;

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;
// find_by_order(k)  returns iterator to kth element starting from 0;
// order_of_key(k) returns count of elements strictly smaller than k;

template<class T>
using min_heap = priority_queue<T,vector<T>,greater<T> >;

/*/---------------------------IO(Debugging)----------------------/*/
template<class T> istream& operator >> (istream &is, vector<T>& V) {
    for(auto &e : V)
        is >> e;
    return is;
}
template<class T, size_t N> istream& operator >> (istream &is, array<T, N>& V) {
    for(auto &e : V)
        is >> e;
    return is;
}
#ifdef __SIZEOF_INT128__
ostream& operator << (ostream &os, __int128 const& value){
    static char buffer[64];
    int index = 0;
    __uint128_t T = (value < 0) ? (-(value + 1)) + __uint128_t(1) : value;
    if (value < 0)
        os << '-';
    else if (T == 0)
        return os << '0';
    for(; T > 0; ++index){
        buffer[index] = static_cast<char>('0' + (T % 10));
        T /= 10;
    }
    while(index > 0)
        os << buffer[--index];
    return os;
}
istream& operator >> (istream& is, __int128& T){
    static char buffer[64];
    is >> buffer;
    size_t len = strlen(buffer), index = 0;
    T = 0; int mul = 1;
    if (buffer[index] == '-')
        ++index, mul *= -1;
    for(; index < len; ++index)
        T = T * 10 + static_cast<int>(buffer[index] - '0');
    T *= mul;
    return is;
}
#endif
template<typename CharT, typename Traits, typename T>
ostream& _containerprint(std::basic_ostream<CharT, Traits> &out, T const &val) {
    return (out << val << " ");
}
template<typename CharT, typename Traits, typename T1, typename T2>
ostream& _containerprint(std::basic_ostream<CharT, Traits> &out, pair<T1, T2> const &val) {
    return (out << "(" << val.first << "," << val.second << ") ");
}
template<typename CharT, typename Traits, template<typename, typename...> class TT, typename... Args>
ostream& operator << (std::basic_ostream<CharT, Traits> &out, TT<Args...> const &cont) {
    out << "[ ";
    for(auto&& elem : cont) _containerprint(out, elem);
    return (out << "]");
}
template<class L, class R> ostream& operator << (ostream& out, pair<L, R> const &val){
    return (out << "(" << val.first << "," << val.second << ") ");
}
template<typename L, size_t N> ostream& operator << (ostream& out, array<L, N> const &cont){
    out << "[ ";
    for(auto&& elem : cont) _containerprint(out, elem);
    return (out << "]");
}
template<class T> ostream& operator<<(ostream &out, ordered_set<T> const& S){
    out << "{ ";
    for(const auto& s:S) out << s << " ";
    return (out << "}");
}
template<class L, class R, class chash = std::hash<L> > ostream& operator << (ostream &out, gp_hash_table<L, R, chash> const& M) {
    out << "{ ";
    for(const auto& m: M) out << "(" << m.first << ":" << m.second << ") ";
    return (out << "}");
}
template<class P, class Q = vector<P>, class R = less<P> > ostream& operator << (ostream& out, priority_queue<P, Q, R> const& M){
    static priority_queue<P, Q, R> U;
    U = M;
    out << "{ ";
    while(!U.empty())
        out << U.top() << " ", U.pop();
    return (out << "}");
}
template<class P> ostream& operator << (ostream& out, queue<P> const& M){
    static queue<P> U;
    U = M;
    out << "{ ";
    while(!U.empty())
        out << U.front() << " ", U.pop();
    return (out << "}");
}
#define TRACE
#ifdef TRACE
    #define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cerr << name << " : " << arg1 << endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ',');
        cerr.write(names, comma - names) << " : " << arg1<<" | ";
        __f(comma+1, args...);
    }
#else
    #define trace(...) 1
#endif

/*/---------------------------RNG----------------------/*/
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int64_t random_long(long long l = LLONG_MIN,long long r = LLONG_MAX){
    uniform_int_distribution<int64_t> generator(l,r);
    return generator(rng);
}
struct custom_hash { // Credits: https://codeforces.com/blog/entry/62393
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    template<typename L, typename R>
    size_t operator()(pair<L,R> const& Y) const{
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(Y.first * 31ull + Y.second + FIXED_RANDOM);
    }
};

/*/---------------------------Defines----------------------/*/
#define ll long long
#define endl "\n"
#define all(v) (v).begin(),(v).end()
/*/-----------------------Modular Arithmetic---------------/*/
int mod ;

/*/-----------------------------Code begins----------------------------------/*/
const int N = 505;
long long dp[N][(N * N)/2];

long long add(long long x, long long y){
	x += y;
	if (x >= mod)
		return x - mod;
	return x;
}
long long sub(long long x, long long y){
	x -= y;
	if (x < 0)
		return x + mod;
	return x;
}
void preprocess(int n){

	dp[0][0] = 1;
	for(int i = 1; i <= n; ++i){
		long long ub = (i * (i - 1)) >> 1;
		long long psum = 0;
		for(int j = 0; j <= ub; ++j){
			psum = add(psum, dp[i - 1][j]);
			if (j > (i - 1)){
				psum = sub(psum, dp[i - 1][j - i]);
			}
			dp[i][j] = psum;
		}
	}
}

long long norm(long long x){
	x %= mod;
	if (x < 0)
		x += mod;
	return x;
}
void solve(){

	int M;
	cin >> M >> mod;
	if (mod == 1){
		cout << 0 << endl;
		return;
	}

	auto cnt_inv = [&] (const vector<int>& a){
		int ret = 0;
		for(int i = 0; i < (int)a.size(); ++i){
			for(int j = i + 1; j < (int)a.size(); ++j){
				if (a[j] < a[i]){
					++ret;
				}
			}
		}
		return ret;
	};
	auto calc = [&] (int n){
		vector<pair<vector<int>, int>> perms;

		vector<int> cur(n);
		for(int i = 0; i < n; ++i){
			cur[i] = i;
		}

		do{
			perms.push_back({cur, cnt_inv(cur)});
		}while(next_permutation(all(cur)));
		sort(all(perms));

		long long x = 0;
		for(int i = 0; i < (int)perms.size(); ++i){
			for(int j = i + 1; j < (int)perms.size(); ++j){
				if (perms[i].second > perms[j].second){
					++x;
					if (perms[i].first[0] == perms[j].first[0]){
						// trace(perms[i].first, perms[j].first);
					}
				}
			}
		}
		return x;
	};
	preprocess(M);

	vector<long long> ans(M + 1);

	for(int n = 4; n <= M; ++n){
		int ub = ((n - 1) * n) / 2;
		vector<long long> use;
		for(int z = 0; z <= ub; ++z){
			use.push_back(dp[n - 1][z]);
		}
		vector<int> p0(ub + 1), p1(ub + 1), p2(ub + 1);

		for(int z = 0; z <= ub; ++z){
			long long tmp = (z * (z - 1)) / 2;
			tmp *= use[z];
			p2[z] = tmp % mod;
			tmp = z * use[z];
			p1[z] = tmp % mod;
			p0[z] = use[z];
			if (z > 0){
				p0[z] = add(p0[z - 1], p0[z]);
				p1[z] = add(p1[z - 1], p1[z]);
				p2[z] = add(p2[z - 1], p2[z]);
			}
		}

		for(int j = 0; j < ub; ++j){
			long long cur = use[j];
			long long j_ub = min(j + n, ub);
			long long contribution = 0;

			if (j_ub < ub){
				contribution = ((n * 1LL * (n - 1)) / 2) * 1LL * (p0[ub] - p0[j_ub]);
				contribution = norm(contribution);
			}
			long long t1 = (j * 1LL * (j + 1)) / 2;
			contribution -= (p2[j_ub] - p2[j + 1]) + (t1 * (p0[j_ub] - p0[j + 1])) - (j * 1LL * (p1[j_ub] - p1[j + 1]));
			contribution = norm(contribution);
			contribution += (p1[j_ub] - p1[j + 1]) * 1LL * n;
			contribution -= (p0[j_ub] - p0[j + 1]) * 1LL * n * 1LL * (j + 1);
			ans[n] = add(ans[n], norm(contribution * cur));
		}

	}

	long long ret = 0;

	long long mult = 1;

	for(int i = M; i >= 1; --i){
		ret = add(ret, norm(ans[i] * mult));
		mult = (mult * i) % mod;
	}
	cout << ret << endl;

}
int main(){
    // Use "set_name".max_load_factor(0.25);"set_name".reserve(512); with unordered set
    // Or use gp_hash_table<X,null_type>
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cout << fixed << setprecision(25);
    cerr << fixed << setprecision(10);
    auto start = std::chrono::high_resolution_clock::now();

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }

    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
    // cerr << "Time taken : " << ((long double)duration.count())/((long double) 1e9) <<"s "<< endl;
}

#include <bits/stdc++.h>

using namespace std;

#define  ll long long
#define ld long double
#define f first
#define s second
const int N = 55;

int n , dp[N][N*N] , S[N][N*N] , ncr[N][N] , fact[N] , mod;

int solve(int i , int rem)
{
    if (i==0)
        return rem==0;

    if (dp[i][rem] != -1)
        return dp[i][rem];

    int ans=0;
    for(int j=0; j<=min(i-1,rem); j++)
    {
        ans = (ans + solve(i-1 , rem-j))%mod;
    }
    return dp[i][rem] = ans;
}

int get(int len)
{
    int ans=0 , mx = len*(len-1)/2 , tmp;

    for(int dif=1; dif<len; dif++) //There can be len-dif positions that generate this difference
    {
        for(int w = dif+1; w<=mx; w++)
        {
            tmp = (1ll*dp[len-1][w]*S[len-1][w-dif-1])%mod;
            tmp = (1ll*tmp*(len-dif))%mod;
            ans = (ans+tmp)%mod;
        }
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> mod;

    memset(dp , -1 , sizeof(dp));
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j <= i*(i-1)/2; j++)
        {
            S[i][j] = solve(i , j);
            if (j) S[i][j] = (S[i][j] + S[i][j-1])%mod;
        }
    }

    int ans = 0 , waysOfPrefix=1;
    for(int i=0; i<n-1; i++) //Brute force on the remaining
    {
        int tmp = (1ll*waysOfPrefix*get(n-i))%mod;
        ans = (ans+tmp)%mod;
        waysOfPrefix = (1ll*waysOfPrefix*(n-i)*(i+1))%mod;
    }

    cout << ans << '\n';

    return 0;
}

/*
fi 表示长度为i的排列，p<q且逆序对数p>q的方案数
gij 表示长度为i的排列，任意放，使得p逆序对数比q多j的方案数

f[n] = \sum A_{n,i} * f[n - i] +
g[i][j] =
*/

#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s^'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T t = 0 , tmp[25] = {};
	while(x) tmp[t ++] = x % 10 , x /= 10;
	while(t -- > 0) putchar(tmp[t] + '0');
	putchar(s);
}

const int N = 1250;

LL n , mod , f[55] , g[55][55 * 55] , A[55][55] , tmp[55 * 55];

void Add(LL &x , LL y) {x = (x + y + mod) % mod;}

int main() {
	read(n),read(mod);
	g[2][1251] = 1;
	g[2][1250] = 2;
	g[2][1249] = 1;
	for (int i = 3; i <= n; ++i) {
		Add(f[i] , i * f[i - 1] % mod);
		for (int j = N - (i - 1) * i / 2; j <= N + i * (i - 1) / 2; ++j) {
			for (int k = 1; k < i; ++k) {
				if(j - k >= 0) Add(g[i][j] , g[i - 1][j - k] * (i - k) % mod);
				if(j + k <= N * 2) Add(g[i][j] , g[i - 1][j + k] * (i - k) % mod);
			}
			Add(g[i][j] , g[i - 1][j] * i % mod);
		}
		tmp[0] = 0;
		for (int j = 1; j <= i * (i - 1) / 2; ++j) tmp[j] = g[i - 1][N + j] , Add(tmp[j] , tmp[j - 1]);
		for (int j = 1; j < i; ++j)
			Add(f[i] , (tmp[i * (i - 1) / 2] - tmp[j]) * (i - j) % mod);
	}
	write(f[4]);
	return 0;
}

#include<iostream>
#include<cstdio>
#define N 500
using namespace std;
long long n,C[N+1][N+1],dp[N+1][N+1],F[N+1][N+1],fac[N+1],mod,ans;
int main()
{
	cin>>n>>mod,fac[0]=1;
	for (int i=1;i<=n;++i) fac[i]=fac[i-1]*i%mod;
	for (int i=0;i<=n;++i) C[i][0]=1;
	for (int i=1;i<=n;++i)
		for (int j=1;j<=i;++j)
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	dp[1][0]=1;
	for (int i=1;i<=n-1;++i)
		for (int j=0;j<=n*n;++j)
			for (int k=0;k<=i;++k)
				if (j+k<=n*n)
					dp[i+1][j+k]=(dp[i+1][j+k]+dp[i][j])%mod;
	for (int i=1;i<=n;++i)
	{
		for (int j=0;j<=i*i;++j)
			for (int k=0;k<=j-1;++k)
				F[i][j-k-1]=(F[i][j-k-1]+dp[i][j]*dp[i][k])%mod;
		for (int j=n*n-1;j>=0;--j) F[i][j]=(F[i][j]+F[i][j+1])%mod;
	}
	for (int a=1;a<=n;++a)
		for (int b=a+1;b<=n;++b)
			for (int cnt1=0;cnt1<=a-1;++cnt1)
				for (int cnt2=0;cnt2<=b-a-1;++cnt2)
					for (int cnt3=0;cnt3<=n-b;++cnt3)
						ans=(ans+C[a-1][cnt1]*C[b-a-1][cnt2]%mod*C[n-b][cnt3]%mod*F[cnt1+cnt2+cnt3+1][cnt2+1]%mod*fac[n-2-cnt1-cnt2-cnt3]%mod)%mod;
	printf("%lld\n",ans);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 59
ll n,p,ans,num[N][N*N],val[N][N*N];
ll work(ll x,ll y)
{
	ll res=0;
	for(int i=0;i<=(n-1)*(n-2)/2;i++)
	{
		if(i+x-y-1<0) continue;
		res=(res+val[n-1][i+x-y-1]*num[n-1][i])%p;
	}
	return res;
}
int main()
{
	scanf("%lld%lld",&n,&p);
	num[1][0]=1;
	for(int i=1;i<n;i++)
		for(int j=0;j<=i*(i-1)/2;j++)
			for(int k=1;k<=i+1;k++)
				num[i+1][j+k-1]=(num[i+1][j+k-1]+num[i][j])%p;
	for(int i=1;i<n;i++)
	{
		val[i][0]=1;
		for(int j=1;j<=i*(i-1)/2;j++) val[i][j]=(val[i][j-1]+num[i][j])%p;
	}
	/*for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=i*(i-1)/2;j++) cout<<num[i][j]<<' ';
		puts("");
	}*/
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			ans=(ans+work(i-1,j-1))%p;
	printf("%lld\n",ans%p);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

template <class T>
inline bool mnto(T& a, T b) {return a > b ? a = b, 1 : 0;}
template <class T>
inline bool mxto(T& a, T b) {return a < b ? a = b, 1: 0;}
#define REP(i, s, e) for (int i = s; i < e; i++)
#define RREP(i, s, e) for (int i = s; i >= e; i--)
typedef long long ll;
typedef long double ld;
#define MP make_pair
#define FI first
#define SE second
typedef pair<int, int> ii;
typedef pair<ll, ll> pll;
#define MT make_tuple
typedef tuple<int, int, int> iii;
#define ALL(_a) _a.begin(), _a.end()
#define pb push_back
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<ii> vii;

#ifdef DEBUG
#define debug(args...) _debug(args)
void _debug(const char* format, ...) {
	va_list args;
	va_start(args, format);
	vprintf(format, args);
	va_end(args);
}
#else
#define debug(args...)
#endif

#define INF 1000000005
#define LINF 1000000000000000005
#define MAXN 55

int n;
int mod;
ll dp[MAXN][MAXN * MAXN], s[MAXN][MAXN * MAXN], ans[MAXN];

int main() {
	scanf("%d %d", &n, &mod);
	dp[0][0] = 1;
	REP (j, 0, n * n) {
		s[0][j] = 1;
	}
	REP (i, 1, n + 1) {
		REP (j, 0, n * n) {
			if (j - i >= 0) {
				dp[i][j] = s[i - 1][j] - s[i - 1][j - i];
			} else {
				dp[i][j] = s[i - 1][j];
			}
			dp[i][j] %= mod;
			debug("%d %d: %lld\n", i, j, dp[i][j]);
			s[i][j] = (j == 0 ? 0 : s[i][j - 1]) + dp[i][j];
			s[i][j] %= mod;
		}
	}
	REP (l, 1, n + 1) {
		REP (i, 1, l + 1) {
			REP (j, i + 1, l + 1) {
				REP (k, 0, l * l) {
					ans[l] += ans[l - 1] * l % mod +
					   	dp[l - 1][k] * s[l - 1][k - (j - i) - 1] % mod;
					ans[l] %= mod;
				}
			}
		}
	}
	printf("%lld\n", ans[n]);
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <chrono>
#include <random>
#include <unordered_map>

using namespace std;
typedef long long ll;

void solve() {
    int n, mod;
    cin >> n >> mod;

    vector<vector<int>> p(n + 1, vector<int>(n * (n - 1) / 2 + 1));
    vector<int> fact(n + 1);
    fact[0] = 1;
    for (int i = 1; i < n + 1; i++) {
        fact[i] = (fact[i - 1] * 1ll * i) % mod;
    }

    p[1][0] = 1;

    for (int i = 2; i < n + 1; i++) {
        int sum = 0;
        for (int j = 0; j < i * (i - 1) / 2 + 1; j++) {
            sum = (sum * 1ll + p[i - 1][j]) % mod;
            if (j >= i)
                sum = (sum * 1ll - p[i - 1][j - i] + mod) % mod;
            p[i][j] = sum;
        }
    }

    vector<vector<int>> r(n + 1, vector<int>(n + 1));

    for (int i = 1; i < n + 1; i++) {
        for (int j = 1; j < n + 1; j++) {
            for (int k = i * (i - 1) / 2; k > 0; k--) {
                if (k >= j)
                    r[i][j] = (r[i][j] * 1ll + (p[i][k - j] * 1ll * p[i][k]) % mod) % mod;
            }
        }
        for (int j = n - 1; j > 0; j--) {
            r[i][j] = (r[i][j] * 1ll + r[i][j + 1]) % mod;
        }
    }

    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = j + 1; k < n; k++) {
                for (int l = 0; l < i + 1 && l < k - j; l++) {
                    ans = (ans * 1ll + (fact[i] * 1ll * r[n - i - 1][k - j - l + 1]) % mod) % mod;
                }
            }
        }
    }

    cout << ans;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#if defined(_DEBUG)
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int q = 1;
    //cin >> q;
    for (int t = 1; t <= q; t++) {
        solve();
        //cout << endl;
    }
}

#include<bits/stdc++.h>
using namespace std;
long long a,b,mod,d[40001],cnt,sum[4005][101];
long long t[4005][101];
int main()
{
	scanf("%lld%lld",&a,&mod);
	if(a==2||a==1)
	{
		printf("0\n");
		return 0;
	}
	d[1]=1;
	d[2]=1;
	cnt=2;
	long long ls=0;
	for(int i=3;i<=a;i++)
	{
		memset(t,0,sizeof(t));
		for(int j=1;j<=i;j++)
		{
			for(int k=1;k<=cnt;k++)
			{
				t[j][k+j-1]=d[k];
				t[j][k+j-1]%=mod;
			}
		}
		memset(d,0,sizeof(d));
		for(int j=1;j<=cnt+i-1;j++)
		{
			for(int k=1;k<=i;k++)
			{
				d[j]+=t[k][j];
				d[j]%=mod;
			}
//			cout<<d[j]<<" ";
		}
		cnt=cnt+i-1;
		memset(sum,0,sizeof(sum));
		for(int j=i;j>=1;j--)
		{
			for(int k=1;k<=cnt;k++)
			{
				sum[j][k]=sum[j][k-1]+sum[j+1][k]-sum[j+1][k-1]+t[j][k];
				sum[j][k]%=mod;
			}
		}
		long long ann=ls%mod*i%mod;
		for(int j=1;j<i;j++)
		{
			for(int k=1;k<=cnt;k++)
			{
//				cout<<t[j][k]<<" ";
				sum[j+1][k-1]%=mod;
				ann+=sum[j+1][k-1]*t[j][k]%mod;
				ann%=mod;
			}
//			cout<<ann<<"\n";
		}
		ls=ann;
	}
//	cout<<cnt<<" ";
//	cout<<ls<<" ";
	printf("%lld",(ls%mod+mod)%mod);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mp make_pair

#define forn(i,n) for(int i = 0;i<int(n);i++)
#define dforn(i,n) for(int i = int(n)-1;i>=0;i--)
#define forsn(i,s,n) for(int i = int(s);i<int(n);i++)
#define fore(i,s,n) for(int i = int(s);i<int(n);i++)
#define dforsn(i,s,n) for(int i = int(n)-1;i>=int(s);i--)

#define DBG(x) do{cout<<#x<<" = "<<x<<endl;}while(false)
#define TAM_MASK 1
#define get(mask,i) ((mask>>(TAM_MASK*(i)) & ( (1<<TAM_MASK)-1)))
#define set(mask,i,v)  ( ((mask & ~( ( (1<<TAM_MASK)-1) << (TAM_MASK*(i)) )) | (v<<(TAM_MASK * (i))) )
#define popcount(mask) (__builtin_popcount(mask))
#define endl '\n'
#define ALL(x) x.begin(),x.end()
template<class T> ostream & operator<<(ostream & out, vector<T> & v){
	out<<"[";
	for(auto k : v) out<<k<<" ";
	out<<"]"<<"\n";
	return out;
}
template<class T> ostream & operator<<(ostream & out, set<T>  s){
	out<<"{";
	for(auto k : s) out<<k<<" ";
	out<<"}"<<"\n";
	return out;
}

template<class T, class U> ostream & operator<<(ostream & out, pair<T,U>  p){
	out<<"[ "<<p.first<<" , "<<p.second<<" ] ";
	return out;
}
template<class T, class U> istream & operator>>(istream & in, pair<T,U> & p){
	in>>p.first>>p.second;
	return in;
}

typedef long long intl;
intl dp[500][501*250];
intl mod = 1e9+7;
intl DP(int n, int inv){
    if(n==1) return (inv==0);
    if(dp[n][inv]!=-1) return dp[n][inv];
    dp[n][inv] = 0;
    forn(i,n){
        dp[n][inv] = (dp[n][inv]+DP(n-1,inv-i))%mod;
    }
    return dp[n][inv];
}
int main()
{
    cin.tie(0);
    cin.sync_with_stdio(0);
    memset(dp,-1,sizeof(dp));
    intl n; cin>>n>>mod;
    intl res = 0;
    forn(i,n){
        forn(a,n)
            forn(b,a){
                intl ac = 0, bc = 0;
                intl dif = a-b+1;
                intl tam = (n-i)*(n-i-1)/2;
                forn(c,tam){
                    ac = (DP(n-i-1,c)) %mod;
                    if(c>=dif){
                        bc = (bc+DP(n-i-1,c-dif));
                    }
                    res = (res+1ll*ac*bc)%mod;
                }
            }
    }
    cout<<res<<endl;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define rep(x,l,r) for(int x=(l);x<=(r);++x)
#define per(x,r,l) for(int x=(r);x>=(l);--x)
const int maxn=505;
int n,mod,dp[maxn][maxn*maxn/2],sum[maxn*maxn/2],g[maxn*maxn/2],ans[maxn];
//dp[i][j]表示1-i的排列中逆序对个数为j的方案数
//以i开头的逆序对个数为j的排列有 dp[n-1][j-(i-1)] 个

int read(){
	int res=0,f=1;char ch;
	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
	do{res=res*10+ch-'0';ch=getchar();}while(isdigit(ch));
	return res*f;
}

signed main(){
	n=read();mod=read();sum[0]=1;
	rep(i,1,n){
		rep(j,0,i*(i-1)/2){
//			rep(k,0,i-1)dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod;
			if(j-i>=0)dp[i][j]=(sum[j]-sum[j-i]+mod)%mod;
			else dp[i][j]=sum[j];
		}
		sum[0]=dp[i][0];
		rep(j,1,i*(i+1)/2)sum[j]=(sum[j-1]+dp[i][j])%mod;
	}
//	rep(N,4,n){
//		rep(i,1,N)rep(p,i+1,N)
//			rep(j,i-1,N*(N-1)/2)rep(q,0,j-p)
//				ans[N]=(ans[N]+1ll*dp[N-1][j-(i-1)]*dp[N-1][q]%mod)%mod;
//		ans[N]=(ans[N]+ans[N-1]*N%mod)%mod;
//	}
	rep(N,4,n){
		g[0]=dp[N-1][0];rep(i,1,(N-1)*(N-2)/2)g[i]=(g[i-1]+dp[N-1][i])%mod;
		rep(i,1,N)rep(p,i+1,N)
			rep(j,p,N*(N-1)/2)
				ans[N]=(ans[N]+1ll*dp[N-1][j-(i-1)]*g[j-p])%mod;
		ans[N]=(ans[N]+ans[N-1]*N%mod)%mod;
	}
	printf("%d\n",ans[n]);
}

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>

typedef long long lint;

#define MAXN 55

using namespace std;

int n, mod;
lint C[MAXN][MAXN], f[2][MAXN * MAXN * 2], sum[MAXN * MAXN * 2];

void init() {
    C[1][1] = 1;
    for (int i = 1; i <= n; ++i)
        C[i][0] = C[0][i] = 1;
    for (int i = 2; i <= n; ++i)
        for (int j = 1; j <= i; ++j)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
}

int main() {
    cin >> n >> mod;
    init();
    int base = n * (n - 1) / 2;
    f[0][base] = 1;
    lint res = 0;
    for (int i = 1; i < n; ++i) {
        int cur = i & 1, pre = cur ^ 1;
        memset(f[cur], 0, sizeof(f[cur]));
        for (int j = -i * (i - 1) / 2 + base; j <= i * (i - 1) / 2 + base; ++j)
            for (int k = max(-(i - 1) * (i - 2) / 2, j - base - i + 1) + base; k <= min((i - 1) * (i - 2) / 2, j - base + i - 1) + base; ++k)
                f[cur][j] = (f[cur][j] + f[pre][k] * (i - abs(j - k)) % mod) % mod;
        for (int j = base * 2; j >= 0; --j)
            sum[j] = (sum[j + 1] + f[cur][j]) % mod;
        for (int j = 1; j <= i; ++j)
            res = (res + (i + 1 - j) * C[n - 2][n - i - 1] * sum[base + j + 1]) % mod;
    }
    cout << res << endl;
}

#include <bits/stdc++.h>

#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort((x).begin(), (x).end()); (x).erase(unique((x).begin(), (x).end()), (x).end())
#define imie(x) #x << ": " << x

using namespace std;

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

template <typename T, typename U>
istream& operator >>(istream& istr, pair<T, U>& pr) {
	return istr >> pr.first >> pr.second;
}

template <typename T = int>
T nxt(istream& istr = cin) {
	T x;
	istr >> x;
	return x;
}

template <typename T>
struct TypeModular {
	using Type = typename decay<decltype(T::value)>::type;
	Type val;

	static constexpr Type mod() {
		return T::value;
	}

	TypeModular(long long _val = 0) {
		if (_val < 0 || (_val > 0 && _val >= mod())) {
			val = _val % mod();
			if (val < 0) {
				val += mod();
			}
		} else {
			val = _val;
		}
	}

	friend TypeModular operator -(const TypeModular& a) {
		return {-a.val};
	}

	friend TypeModular operator +(const TypeModular& a, const TypeModular& b) {
		Type res = a.val + b.val;
		if (res >= mod()) {
			res -= mod();
		}
		return {res};
	}

	friend TypeModular operator -(const TypeModular& a, const TypeModular& b) {
		Type res = a.val - b.val;
		if (res < 0) {
			res += mod();
		}
		return {res};
	}

	friend TypeModular operator *(const TypeModular& a, const TypeModular& b) {
		return {1ll * a.val * b.val};
	}

	friend TypeModular operator /(const TypeModular& a, const TypeModular& b) {
		return a * b.inv();
	}

	TypeModular& operator +=(const TypeModular& b) {
		val += b.val;
		if (val >= mod()) {
			val -= mod();
		}
		return *this;
	}

	TypeModular& operator -=(const TypeModular& b) {
		val -= b.val;
		if (val < 0) {
			val += mod();
		}
		return *this;
	}

	TypeModular& operator *=(const TypeModular& b) {
		val = 1ll * val * b.val % mod();
		return *this;
	}

	TypeModular& operator /=(const TypeModular& b) {
		*this *= b.inv();
		return *this;
	}

	TypeModular& operator ++() {
		val += 1;
		if (val == mod()) {
			val = 0;
		}
		return *this;
	}

	TypeModular operator ++(int) {
		TypeModular tmp(*this);
		operator ++();
		return tmp;
	}

	friend bool operator ==(const TypeModular& a, const TypeModular& b) {
		return a.val == b.val;
	}

	friend bool operator !=(const TypeModular& a, const TypeModular& b) {
		return a.val != b.val;
	}

	TypeModular pow(long long b) const {
		TypeModular res{1}, a{*this};
		while (b) {
			if (b & 1ll) {
				res *= a;
			}
			b >>= 1;
			a *= a;
		}
		return res;
	}

	TypeModular inv() const {
		assert(val);
		return _inv(val, mod());
	}

	int _inv(int a, int b) const {
		return a == 1 ? a : b - 1ll * _inv(b % a, a) * b / a % b;
	}

	explicit operator Type() const {
		return val;
	}

	explicit operator bool() const {
		return val;
	}
};

template <typename T = int>
struct integral_variable {
	static T value;
};

template <typename T> T integral_variable<T>::value;

void set_prime(int p) {
	integral_variable<int>::value = p;
}

template <typename T>
ostream& operator <<(ostream& ostr, const TypeModular<T>& x) {
	return ostr << x.val;
}

template <typename T>
istream& operator >>(istream& istr, TypeModular<T>& x) {
	x = nxt(istr);
	return istr;
}

template <int mod>
using Modular = TypeModular<integral_constant<int, mod>>;
#define all(x) (x).begin(), (x).end()
#define itn int
#define make_unique(x) sort((x).begin(), (x).end()); (x).erase(unique((x).begin(), (x).end()), (x).end())

inline int nxt() {
	int x;
	cin >> x;
	return x;
}

using Mint = TypeModular<integral_variable<int>>;

const int N = 505;
const int M = N * N / 2;
Mint with_inv[N][M];
Mint tmp[M];
Mint huemp[M];

Mint C[N][N];

void solve() {
	int nn = nxt(), mod = nxt();
	set_prime(mod);

	with_inv[0][0] = 1;
	for (int n = 1; n < N; ++n) {
		Mint cur = 0;
		for (int i = 0; i <= n * (n - 1) / 2; ++i) {
			cur += with_inv[n - 1][i];
			if (i >= n) {
				cur -= with_inv[n - 1][i - n];
			}
			with_inv[n][i] = cur;
		}
	}
	for (int i = 0; i < N; ++i) {
		C[i][0] = C[i][i] = 1;
		for (int j = 1; j < i; ++j) {
			C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
		}
	}

	Mint ans = 0;
	for (int n = 2; n < nn; ++n) {
		Mint cur = 0;
		partial_sum(with_inv[n], with_inv[n] + n * (n - 1) / 2 + 1, tmp);
		for (int d = 1; d <= n; ++d) {
			for (int i = d + 1; i <= n * (n - 1) / 2; ++i) {
				cur += with_inv[n][i] * tmp[i - d - 1] * (n + 1 - d);
			}
		}
		ans += cur * C[nn - 1][n];
	}
	cout << ans << "\n";
}

int main() {
	int t = 1; // nxt();
	while (t--) {
		solve();
	}

	return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<ll,ll> pi;
typedef vector <ll> vi;
typedef vector <pi> vpi;
typedef pair<pi,ll> pii;
typedef set <ll> si;
typedef long double ld;
#define f first
#define s second
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
#define aFOR(i,x) for (auto i: x)
#define mem(x,i) memset(x,i,sizeof x)
#define fast ios_base::sync_with_stdio(false),cin.tie(0)
#define int ll
#define maxn 51

int dp[maxn][maxn * maxn], ss[maxn][maxn * maxn], A[maxn][maxn], fac[maxn], facinv[maxn];
int N, MOD;
int nckmemo[maxn][maxn];

int qryss(int ssarr[], int i,int j){
	if (i > j) return 0;
	if (i == 0) return ssarr[j];
	return (ssarr[j] - ssarr[i-1] + MOD) % MOD;
}

int nck(int n,int k){
	if (n < k) return 0;
	if (k == 0) return 1;
	if (n == 0) return 0;
	if (nckmemo[n][k] != -1) return nckmemo[n][k];
	return nckmemo[n][k] = (nck(n-1,k) + nck(n-1,k-1)) % MOD;
}
int32_t main(){
	fast;

	cin >> N >> MOD;

	fac[0] = 1;
	FOR(i,1,N) fac[i] = (fac[i-1] * i) % MOD;
	FOR(i,0,N) dp[i][0] = ss[i][0] = 1;
	FOR(j,1,N) dp[0][j] = 0;

	FOR(i,0,N) FOR(j,1,N * N){
		if (i > 0) dp[i][j] = qryss(ss[i-1], max(j - i + 1, 0LL), j);
		ss[i][j] = (ss[i][j - 1] + dp[i][j]) % MOD;
	}

	//~ FOR(i,1,N){
		//~ FOR(j,1,N * N) cout << dp[i][j] << ' ';
		//~ cout << '\n';
	//~ }
	// A[i][j] = Number of pairs of permutation of size i which inversions differ by > j

	FOR(i,0,N) FOR(k,0,N) FOR(j,k+1,N*N) {
		(A[i][k] += ((ss[i][j - k - 1] * dp[i][j]) % MOD)) %= MOD;
		//~ A[i][k] %= MOD;
	}
	mem(nckmemo,-1);
	int ans = 0;
	FOR(k,0,N-1){
		FOR(a,1,N) FOR(b,a+1,N){
			(ans += (((fac[k] * nck(N - 1, k)) % MOD) * A[N-k-1][b-a]) % MOD) %= MOD;

			//~ (res += A[N - k - 1][b - a]) %= MOD;
		}
		//~ (ans += (res * fac[k]) % MOD) %= MOD;
	}

	cout << ans;

}

#include "bits/stdc++.h"

using namespace std;

const int N = 55;

long long mod;
long long F[N];
long long dp[N][N*N];
long long sum[N][N*N];
long long DP[N][N*N];
long long C[N][N];

long long memo(int n, int d) {
    int m = n * (n - 1) / 2;
    if(d > m) return 0;
    if(DP[n][d] != -1) return DP[n][d];
    long long ans = memo(n, d+1);
    for(int i=m; i>=0; i--) {
        ans += dp[n][i] * dp[n][i-d];
    }
    return DP[n][d] = ans;
}

long long get(int n) {
    long long ans = 0;
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {
            int diff = j - i + 1;
            ans += memo(n-1, diff);
            ans %= mod;
        }
    }
    return ans;
}

void init() {
    memset(DP, -1, sizeof DP);
    memset(dp, 0, sizeof dp);
    dp[1][0] = 1;
    for(int i=2; i<N; i++) {
        for(int j=0; j<=i*(i-1)/2; j++) {
            for(int k=1; k<=i && j - k + 1 >= 0; k++) {
                dp[i][j] += dp[i - 1][j - k + 1];
            }
        }
    }
}

long long cc(int n, int k) {
    // if(k < 0 || k > n) return 0;
    if(k == 0 || k == n) return 1%mod;
    if(C[n][k] != -1) return C[n][k];
    return C[n][k] = (cc(n-1, k) + cc(n-1, k-1)) % mod;
}

void solve() {
    init();
    memset(C, -1, sizeof C);
    int n;
    cin >> n >> mod;
    F[0] = 1%mod;
    for(int i=1; i<N; i++) F[i] = (F[i-1] * i) % mod;
    long long ans = 0;
    for(int pre=0; pre<n-1; pre++) {
        long long pref = (F[pre] * cc(n, pre)) % mod;
        ans = (ans + (pref * get(n-pre)) % mod) % mod;
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int tc = 1;
    // cin >> tc;
    for(int qq = 1; qq <= tc; qq++) {
        // cout << "Case #" << i << ":";
        solve();
    }

    return 0;
}

using namespace std;

#include <iostream>

#define MAXN 505

int N;
long long dp[MAXN][MAXN * MAXN / 2],dp2[MAXN][MAXN],fact[MAXN],nCr[MAXN][MAXN],MOD;

int main() {
	cin >> N >> MOD;
	fact[0] = nCr[0][0] = 1;
	for(int i = 1;i <= N;++i) {
		for(int j = 0;j <= i;++j) {
			nCr[i][j] = (i > 0 ? nCr[i - 1][j - 1] : 0) + nCr[i - 1][j];
			if(nCr[i][j] >= MOD) nCr[i][j] -= MOD;
		}
	}
	// dp[i][j] = Number of permutations of length i with j inversions
	dp[1][0] = 1;
	for(int i = 2;i <= N;++i) {
		long long pref = 0;
		for(int j = 0;j <= i * (i - 1) / 2;++j) {
			pref += dp[i - 1][j];
			if(j >= i) pref += MOD - dp[i - 1][j - i];
			dp[i][j] = pref %= MOD;
		}
	}
	// dp2[i][j] = Number pair of permutations with difference in inversion of j of length i
	for(int i = 1;i <= N;++i) {
		for(int j = 0;j <= N;++j) {
			for(int k = 0;k + j <= i * (i - 1) / 2;++k) {
				dp2[i][j] += dp[i][k] * dp[i][k + j] % MOD;
				if(dp2[i][j] >= MOD) dp2[i][j] -= MOD;
			}
		}
	}
	for(int i = 1;i <= N;++i) {
		for(int j = N - 1;j >= 0;--j) {
			dp2[i][j] += dp2[i][j + 1];
			if(dp2[i][j] >= MOD) dp2[i][j] -= MOD;
		}
	}
	long long ans = 0;
	// First differ in position i
	for(int i = 0;i < N;++i) {
		// Actual permutation is of length (N - i - 1)
		long long sum = 0;
		// First position of p
		for(int j = 0;j < N - i;++j) {
			// First position of q
			for(int k = j + 1;k < N - i;++k) {
				int dif = k - j;
				sum += dp2[N - i - 1][dif + 1];
				if(sum >= MOD) sum -= MOD;
			}
		}
		// Choose (N - i) out of N numbers, then permute first i numbers
		sum = (sum * nCr[N][N - i] % MOD) * fact[i] % MOD;
		// cout << i << " " << nCr[N][N - i] << " " << fact[i] << " " << sum << endl;
		ans += sum;
		if(ans >= MOD) ans -= MOD;
	}
	cout << ans << endl;
	return 0;
}

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,abm,mmx,avx,avx2,popcnt")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <set>
#include <map>
#include <deque>
#include <string>
#include <cstdint>
#include <cmath>
#include <queue>
#include <cassert>
#include <random>
#include <bitset>
#include <iomanip>
#include <cstring>
#include <numeric>
#include <time.h>//////////////
#include <ctime>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <complex>
#include <chrono>
#include <unordered_set>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

#define all(a) (a).begin(), (a).end()
#define pbc push_back
#define pob pop_back()
#define vin(a) for (auto& i : a) cin >> i
#define sp system("pause")
#define mp make_pair
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

template<typename T1, typename T2>
inline void chkmin(T1& x, const T2& y)
{
    if (y < x) x = y;
}

template<typename T1, typename T2>
inline void chkmax(T1& x, const T2& y)
{
    if (x < y) x = y;
}

double getTime() { return clock() / (double)CLOCKS_PER_SEC; }

mt19937 rnd(time(0));
const int MAXN = 101;
int  mod = 1000000007;
int mul(int a, int b)
{
    return 1ll * a * b % mod;
}
int add(int a, int b)
{
    if (a + b >= mod) return a + b - mod;
    return a + b;
}
int sub(int a, int b)
{
    if (a - b < 0) return a - b + mod;
    return a - b;
}
int binpow(int a, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1)res = mul(res, a);
        a = mul(a, a);
        b >>= 1;
    }
    return res;
}
int inv(int x)
{
    return binpow(x, mod - 2);
}
int fact[MAXN]; int rfact[MAXN];
int cnk(int n, int k)
{
    if (k<0 || k>n) return 0;
    return mul(fact[n], mul(rfact[k], rfact[n - k]));
}
int f[MAXN][MAXN * MAXN];
int calcf(int n, int rv)
{
    if (n == 1)
    {
        return rv == 0;
    }
    if (rv < 0)
    {
        return 0;
    }
    if (f[n][rv] >= 0) return f[n][rv];

    f[n][rv] = 0;
    for (int elem = 1; elem <= n; ++elem)
    {
        f[n][rv] = add(f[n][rv], calcf(n - 1, rv - n + elem));
    }
    return f[n][rv];
}
int cc[MAXN][MAXN];
signed main()
{
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cout.precision(20), cout.setf(ios::fixed);
    memset(f, -1, sizeof f);
    int n;
    cin >> n >> mod;

    cc[0][0] = 1;
    for (int i = 1; i < MAXN; ++i)
    {
        cc[i][0] = 1;
        for (int j = 1; j <= i; ++j)
        {
            cc[i][j] = add(cc[i - 1][j], cc[i - 1][j - 1]);
        }
    }
    fact[0] = 1;
    for (int i = 1; i < MAXN; ++i) fact[i] = mul(fact[i - 1], i);
    rfact[MAXN - 1] = inv(fact[MAXN - 1]);
    for (int i = MAXN - 2; i >= 0; --i)rfact[i] = mul(rfact[i + 1], i + 1);
    int ans = 0;
    int last = 0;
    for (int len = n - 1; len >= 0; --len)
    {
        int x = cc[n][len];
        x = mul(x, fact[len]);
        int rofl = 0;
        vector<int> prefsum(n * (n - 1) / 2 + 1);
        for (int j = 0; j < prefsum.size(); ++j)
        {
            prefsum[j] = add((j == 0 ? 0 : prefsum[j - 1]), calcf(n - len - 1, j));
        }
        for (int nel = 1; nel <= n - len; ++nel)
        {
            for (int nel2 = nel + 1; nel2 <= n - len; ++nel2)
            {
                int  st1 = nel - 1;
                int st2 = nel2 - 1;

                for (int i1 = st2+st1+1; i1 <= n * (n - 1) / 2; ++i1)
                {
                    int m2 = i1 + st1 - st2 - 1;

                    if (m2 >= 0) rofl = add(rofl, mul(calcf(n-len-1,i1),prefsum[m2]));
                }
            }
        }
        x = mul(x, rofl);
        ans = add(ans, sub(x, last));

    }
    cout << ans;
    //sp;
}

#include <bits/stdc++.h>
#pragma GCC optimize("-O3")
#pragma GCC optimize("unroll-loops")
//#include "testlib.h"
//#pragma GCC optimize("popcnt")
#include <random>
#include <time.h>
#define ll long long
#define ull unsigned long long
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define fi first
#define se second
#define pll pair<ll,ll>
#define pii pair<int,int>
#define ld long double

using namespace std;

mt19937_64 rnd(time(0));

ll MOD=998244353;

ll K=125250;

ll n, m, k, ans, a[505], c[505][505], md, dp1[300001], pr[300001], dp2[300001], fact[505], infact[505];

ll binpow(ll h,ll r,ll md)
{
    ll l=1;
    while (r)
    {
        if (r&1) l=(l*h)%md;
        h=(h*h)%md;
        r/=2;
    }
    return l;
}

ll read()
{
    char c=getchar();
    while (!isdigit(c))
    {
        c=getchar();
    }
    ll res=0;
    while (isdigit(c))
    {
        res=res*10+c-'0';
        c=getchar();
    }
    return res;
}

ll gcd(ll x,ll y)
{
    while (x && y)
    {
        if (x<y) swap(x, y);
        x%=y;
    }
    return x+y;
}

void make(int h)
{
    if (h>=n) return;

    ll y=0;

    for (int i = 1; i <= h; i++)
    {
        ll o=0;
        for (int p = i+1; p <= h*(h-1)/2; p++)
        {
            o=(o+dp1[p]*pr[p-i-1]%md)%md;
        }
        o=(o*(n-i))%md;
        y=(y+o)%md;
    }

    y=(y*c[n][h+1]%md*fact[n-h-1]%md)%md;

    //cout << h << " " << y << "\n";

    ans=(ans+y)%md;
}

void solve()
{
    cin >> n >> md;

    fact[0]=1;
    infact[0]=1;

    MOD=md;

    for (int i = 1; i <= n; i++)
    {
        fact[i]=fact[i-1]*i%md;
        infact[i]=binpow(fact[i], md-1, md);
    }

    for (int i = 0; i <= n; i++)
        c[i][0]=1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%md;
        }

    dp1[0]=1;
    pr[0]=1;
    pr[1]=1;

    make(1);

    for (int i = 2; i < n; i++)
    {
        for (int j = 0; j <= i*(i-1)/2; j++)
        {
            dp1[j]=pr[j];
            if (j-i>=0) dp1[j]=dp1[j]-pr[j-i]+md, dp1[j]%=md;
        }
        //cout << i << " :\n";
        for (int j = 0; j <= i*(i+1)/2; j++)
        {
            pr[j]=((j==0?0:pr[j-1])+dp1[j])%md;
            //cout << " " << j << " " << dp1[j] << " " << pr[j] << "\n";
        }
        make(i);
    }

    cout << ans << "\n";
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    ll t=1;
    //cin>> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define  GODSPEED       ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(12);
#define  f              first
#define  s              second
#define  newl           cout<<"\n";
#define  pb             push_back
#define  mset(a,x)      memset(a,x,sizeof(a))
#define  debv(a)        for(auto it: a)cout<<it<<" ";newl;
#define  deb1(a)        cout<<a<<"\n";
#define  deb2(a,b)      cout<<a<<" "<<b<<"\n";
#define  deb3(a,b,c)    cout<<a<<" "<<b<<" "<<c<<"\n";
#define  deb4(a,b,c,d)  cout<<a<<" "<<b<<" "<<c<<" "<<d<<"\n";
#define  uniq(a)        a.resize(unique(a.begin(), a.end()) - a.begin());
#define  all(a)         a.begin(),a.end()

typedef  long long             ll;
typedef  long double           ld;
typedef  pair<ll, ll>           pll;
typedef  vector<ll>            vll;
typedef  vector<pll>           vpll;

const ll   N     =  55;
// const ll   mod   =  998244353;
const ll   INF   =  0x7f7f7f7f7f7f7f7f;
const int  INFi  =  0x7f7f7f7f;
const ll   LEVEL =  log2(N) + 1;

ll n, dp[N][N * N], mod;

ll mem(int i, int j) {
	if (j < 0) return 0;
	if (i == 0) {
		return j == 0;
	}
	if (dp[i][j] != -1) return dp[i][j];
	dp[i][j] = 0;
	for (int ii = 0; ii < i; ii++) {
		dp[i][j] += mem(i - 1, j - ii);
		dp[i][j] %= mod;
	}
	return dp[i][j];
}

void solve() {
	cin >> n >> mod;
	mset(dp, -1);
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= n * n; j++) {
			mem(i, j);
		}
	}
	ll ans = 0;
	for (int i = 1; i < n; i++) {
		for (int dif = 1; dif < n; dif++) {
			ll res = 0;
			for (int p = n * n, q = n * n - dif - 1; q >= 0; p--, q--) {
				res = (res + mem(n - i, p)) % mod;
				ans += (n - dif) * res % mod * mem(n - i, q) % mod;
				ans %= mod;
			}
		}
	}
	deb1(ans)
}

int main() {
	GODSPEED;
	int test = 1;
	// cin >> test;
	for (int i = 1; i <= test; i++) {
		solve();
	}
}

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <tuple>
#include <cmath>
#include <numeric>
#include <functional>
#include <cassert>

#define debug_value(x) cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << #x << "=" << x << endl;
#define debug(x) cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << x << endl;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

using namespace std;
typedef long long ll;

template<typename T>
vector<vector<T>> vec2d(int n, int m, T v){
    return vector<vector<T>>(n, vector<T>(m, v));
}

template<typename T>
vector<vector<vector<T>>> vec3d(int n, int m, int k, T v){
    return vector<vector<vector<T>>>(n, vector<vector<T>>(m, vector<T>(k, v)));
}

template<typename T>
void print_vector(vector<T> v, char delimiter=' '){
    if(v.empty()) {
        cout << endl;
        return;
    }
    for(int i = 0; i+1 < v.size(); i++) cout << v[i] << delimiter;
    cout << v.back() << endl;
}

ll MOD = 1000000007;

class ModInt{
    public:
    ll v;
    ModInt(ll _v = 0){
        if(_v < 0) _v = (_v%MOD)+MOD;
        if(_v >= MOD) _v %= MOD;
        v = _v;
    }
    ModInt operator+(ll n){
        return ModInt((v+n)%MOD);
    }
    ModInt operator-(ll n){
        return ModInt((v-n+MOD)%MOD);
    }
    ModInt operator*(ll n){
        if(n >= MOD) n %= MOD;
        return ModInt((v*n)%MOD);
    }
    ModInt operator/(ll n){
        return ModInt((ModInt(n).inv()*v).v%MOD);
    }

    ModInt &operator+=(ll n){
        v = (v+n)%MOD;
        return *this;
    }
    ModInt &operator-=(ll n){
        v = (v-n+MOD)%MOD;
        return *this;
    }
    ModInt &operator*=(ll n){
        v = (v*n+MOD)%MOD;
        return *this;
    }

    ModInt operator+(ModInt n){
        return ModInt((v+n.v)%MOD);
    }
    ModInt operator-(ModInt n){
        return ModInt((v-n.v+MOD)%MOD);
    }
    ModInt operator*(ModInt n){
        return ModInt((v*n.v)%MOD);
    }
    ModInt operator/(ModInt n){
        return ModInt((n.inv()*v).v%MOD);
    }

    ModInt &operator+=(ModInt n){
        v = (v+n.v)%MOD;
        return *this;
    }
    ModInt &operator-=(ModInt n){
        v = (v-n.v+MOD)%MOD;
        return *this;
    }
    ModInt &operator*=(ModInt n){
        v = (v*n.v)%MOD;
        return *this;
    }

    bool operator==(ModInt n){
        return v == n.v;
    }
    bool operator!=(ModInt n){
        return v != n.v;
    }
    ModInt &operator=(ll n){
        v = n%MOD;
        return *this;
    }

    ModInt inv(){
        if(v == 1) return ModInt(1);
        else return ModInt(MOD-ModInt(MOD%v).inv().v*(MOD/v)%MOD);
    }
};

ostream& operator<<(ostream& os, const ModInt& m){
    os << m.v;
    return os;
}

istream & operator >> (istream &in,  ModInt &m){
    in >> m.v;
    return in;
}

ModInt pow(ModInt a, ll n) {
    assert(n >= 0);
	ModInt ans = 1;
    while (n > 0) {
        if (n&1) ans = ans*a;
        a = a*a;
        n >>= 1;
    }
	return ans;
}

template<typename T>
class CumsumGrid{
    public:
    CumsumGrid(vector<vector<T>> v): v(v){
        n = v.size();
        m = v[0].size();
        v_cumsum = vector<vector<T>>(n+1, vector<T>(m+1, T(0)));
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++){
                v_cumsum[i+1][j+1] = v_cumsum[i+1][j]+v_cumsum[i][j+1]-v_cumsum[i][j]+v[i][j];
            }
        }
    }
    /**
     * v[l] + ... + v[r-1]
     */
    T sum(int il, int ir, int jl, int jr){
        if(ir <= il) return T(0);
        if(jr <= jl) return T(0);
        if(ir > n) ir = n;
        if(jr > m) jr = m;
        if(il < 0) il = 0;
        if(jl < 0) jl = 0;
        return v_cumsum[ir][jr]-v_cumsum[ir][jl]-v_cumsum[il][jr]+v_cumsum[il][jl];
    }
    private:
    int n, m;
    vector<vector<T>> v;
    vector<vector<T>> v_cumsum;
};

const int N_MAX = 1000;
ModInt cb[1005][1005], fac[1005];

void init(){
    cb[0][0] = 1;
    fac[0] = 1;
    for(int n = 1; n <= N_MAX; n++){
        cb[n][0] = 1;
        fac[n] = fac[n-1]*n;
        for(int r = 1; r <= n; r++){
            cb[n][r] = cb[n-1][r]+cb[n-1][r-1];
        }
    }
}

ModInt comb(ll n, ll r){
    if(n < r){
        return ModInt(0);
    }else{
        return cb[n][r];
    }
}

using mint = ModInt;

int tri(int x){
    return (x*(x-1))/2;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << setprecision(10) << fixed;
    int n; cin >> n >> MOD;
    init();
    auto count = vec2d(n+1, tri(n)+1, mint(0));
    auto dp = vec3d(n+1, n, tri(n)+1, mint(0));
    count[0][0] = 1;
    for(int len = 1; len <= n; len++){
        for(int i = 0; i < len; i++){
            int tmp_inv = i;
            for(int pre_inv = 0; pre_inv <= tri(len-1); pre_inv++){
                int inv = pre_inv+tmp_inv;
                count[len][inv] += count[len-1][pre_inv];
                dp[len][i][inv] += count[len-1][pre_inv];
            }
        }
    }
    mint ans = 0;
    for(int i = 0; i < n; i++){
        // 初めてp[i] != q[i]となる
        // p[i] < q[i]
        int len = n-i;
        auto grid_cumsum = CumsumGrid<mint>(dp[len]);
        for(int pi = 0; pi < len; pi++){
            for(int pinv = 0; pinv <= tri(len); pinv++){
                ans += grid_cumsum.sum(pi+1, len, 0, pinv)*dp[len][pi][pinv]*comb(n, len)*comb(n, len)*fac[i];
            }
        }
    }
    cout << ans << endl;
}

#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) pc('-'),x=-x;
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=2e5;
typedef ll fuko[yuzu|10];
ll dp[55][2775],f[55];
int main() {
  ll n,mod,j,i,k,l,o;
  read(n),read(mod);
  dp[1][0]=1;
  for (i=2;i<=n;++i) {
    for (j=0;j+(i-1)*(i-2)/2<=i*(i-1)/2;++j) {
      for (k=0;k<=(i-1)*(i-2)/2;++k) {
        dp[i][j+k]=(dp[i][j+k]+dp[i-1][k])%mod;
      }
    }
  }
  for (i=4;i<=n;++i) {
    f[i]=i*f[i-1]%mod;
    for (k=1;k<i;++k) {
      for (j=0;j+k+1<=(i-1)*(i-2)/2;++j) {
        f[i]=(f[i]+dp[i-1][j]*dp[i-1][j+k+1]%mod*((i-1)*i/2-(i-k)*(i-k-1)/2+mod)%mod)%mod;
      }
    }
  }
  printf("%lld\n",f[n]%mod);
}

#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <cassert>
#include <set>
#include <unordered_map>
#include <cstring>
#include <map>
#include <numeric>
#include <bitset>
#include <random>

#define sz(a) (int)(a).size()
#define all(a) begin(a), end(a)

using namespace std;

using ll = long long;
using ld = long double;

int mod;

int sum(int a, int b) { return (a + b) % mod; }
void add(int& a, int b) { a = sum(a, b); }
int prod(int a, int b) { return (ll)a * b % mod; }
void mul(int& a, int b) { a = prod(a, b); }
int dif(int a, int b) { return (mod + a - b) % mod; } // ((a - b) % mod + mod) % mod;
void sub(int& a, int b) { a = dif(a, b); }

const int maxn = 505;
const int maxinvs = maxn * (maxn - 1) / 2;

int _dp[maxn][2 * maxinvs];
int _pref[2 * maxinvs];
int _prod_pref[2 * maxinvs];
int _rev_prod_pref[2 * maxinvs];

inline int& dp(int i, int j) {
    return _dp[i][j + maxinvs];
}

inline int& pref(int i) {
    return _pref[i + maxinvs];
}

inline int& prod_pref(int i) {
    return _prod_pref[i + maxinvs];
}

inline int& rev_prod_pref(int i) {
    return _rev_prod_pref[i + maxinvs];
}

int seg_sum(int l, int r) {
    return dif(pref(r), pref(l - 1));
}

int seg_dot(int l, int r) {
    int a = seg_sum(l, r);
    int b = dif(prod_pref(r), prod_pref(l - 1));
    sub(b, prod(a, l - 1));
    return b;
}

int seg_rev_dot(int l, int r) {
    int a = seg_sum(l, r);
    int b = dif(rev_prod_pref(r), rev_prod_pref(l - 1));
    sub(b, prod(a, maxinvs - r - 1));
    return b;
}

void calc_pref_sums(int i) {
    for (int j = -i * (i + 1); j <= i * (i + 1); ++j) {
        pref(j) = sum(pref(j - 1), dp(i, j));
        prod_pref(j) = sum(prod_pref(j - 1), prod(dp(i, j), j));
        rev_prod_pref(j) = sum(rev_prod_pref(j - 1), prod(dp(i, j), (maxinvs - j)));
    }
}

int C[maxn][maxn];
int F[maxn];

void comba() {
    C[0][0] = 1;
    for (int i = 1; i < maxn; ++i) {
        for (int j = 0; j <= i; ++j) {
            C[i][j] = C[i - 1][j];
            if (j > 0) {
                add(C[i][j], C[i - 1][j - 1]);
            }
        }
    }

    F[0] = 1;
    for (int i = 1; i < maxn; ++i) {
        F[i] = prod(F[i - 1], i);
    }
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n >> mod;

    comba();

    dp(0, 0) = 1;
    dp(1, 0) = 1;

    calc_pref_sums(1);

    for (int i = 2; i <= n; ++i) {
        int min_j = -i * (i - 1) / 2;
        int max_j = i * (i - 1) / 2;
        for (int j = min_j; j <= max_j; ++j) {
            add(dp(i, j), prod(dp(i - 1, j), i));
            add(dp(i, j), seg_dot(j - i + 1, j - 1));
            add(dp(i, j), seg_rev_dot(j + 1, j + i - 1));
        }
        calc_pref_sums(i);
    }

    for (int i = 0; i <= n; ++i) {
        int min_j = -i * (i - 1) / 2;
        int max_j = i * (i - 1) / 2;
        for (int j = max_j; j >= min_j; --j) {
            add(dp(i, j), dp(i, j + 1));
        }
    }

//    for (int i = 1; i <= n; ++i) {
//        int max_j = i * (i - 1) / 2;
//        int min_j = -max_j;
//        for (int j = min_j; j <= max_j; ++j) {
//            if (dp(i, j)) {
//                cout << i << " " << j << ": " << dp(i, j) << "\n";
//            }
//        }
//    }

    int ans = 0;

    for (int i = 0; i <= n - 1; ++i) {
        int suf = n - i - 1;
        for (int d = 1; d <= n - 1; ++d) {
            for (int between = max(0, d - 1 - i); between <= min(d - 1, suf); ++between) {
                int ways = n - d;
                mul(ways, C[d - 1][between]);
                mul(ways, C[n - 2 - (d - 1)][i - (d - 1 - between)]);
                mul(ways, F[i]);

                int bigger_invs = between + 1;

                add(ans, prod(ways, dp(suf, bigger_invs + 1)));
            }
        }
    }

    cout << ans;

    return 0;
}

// ¯\_(ツ)_/¯
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;

#define all(x)                      (x).begin(),(x).end()
#define X                           first
#define Y                           second
#define sep                         ' '
#define endl                        '\n'
#define debug(x)                    cerr << #x << ": " <<  x << endl;

const ll MAXN = 1e6 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7; // 998244353; // 1e9 + 9;

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	return 0;
}

/*/ Author: kal013 /*/
// #pragma GCC optimize ("O3")
#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
using namespace std;
using namespace __gnu_pbds;

template<class T>
using ordered_set = tree<T, null_type,less<T>, rb_tree_tag, tree_order_statistics_node_update> ;

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;
// find_by_order(k)  returns iterator to kth element starting from 0;
// order_of_key(k) returns count of elements strictly smaller than k;

template<class T>
using min_heap = priority_queue<T,vector<T>,greater<T> >;

/*/---------------------------IO(Debugging)----------------------/*/
template<class T> istream& operator >> (istream &is, vector<T>& V) {
    for(auto &e : V)
        is >> e;
    return is;
}
template<class T, size_t N> istream& operator >> (istream &is, array<T, N>& V) {
    for(auto &e : V)
        is >> e;
    return is;
}
#ifdef __SIZEOF_INT128__
ostream& operator << (ostream &os, __int128 const& value){
    static char buffer[64];
    int index = 0;
    __uint128_t T = (value < 0) ? (-(value + 1)) + __uint128_t(1) : value;
    if (value < 0)
        os << '-';
    else if (T == 0)
        return os << '0';
    for(; T > 0; ++index){
        buffer[index] = static_cast<char>('0' + (T % 10));
        T /= 10;
    }
    while(index > 0)
        os << buffer[--index];
    return os;
}
istream& operator >> (istream& is, __int128& T){
    static char buffer[64];
    is >> buffer;
    size_t len = strlen(buffer), index = 0;
    T = 0; int mul = 1;
    if (buffer[index] == '-')
        ++index, mul *= -1;
    for(; index < len; ++index)
        T = T * 10 + static_cast<int>(buffer[index] - '0');
    T *= mul;
    return is;
}
#endif
template<typename CharT, typename Traits, typename T>
ostream& _containerprint(std::basic_ostream<CharT, Traits> &out, T const &val) {
    return (out << val << " ");
}
template<typename CharT, typename Traits, typename T1, typename T2>
ostream& _containerprint(std::basic_ostream<CharT, Traits> &out, pair<T1, T2> const &val) {
    return (out << "(" << val.first << "," << val.second << ") ");
}
template<typename CharT, typename Traits, template<typename, typename...> class TT, typename... Args>
ostream& operator << (std::basic_ostream<CharT, Traits> &out, TT<Args...> const &cont) {
    out << "[ ";
    for(auto&& elem : cont) _containerprint(out, elem);
    return (out << "]");
}
template<class L, class R> ostream& operator << (ostream& out, pair<L, R> const &val){
    return (out << "(" << val.first << "," << val.second << ") ");
}
template<typename L, size_t N> ostream& operator << (ostream& out, array<L, N> const &cont){
    out << "[ ";
    for(auto&& elem : cont) _containerprint(out, elem);
    return (out << "]");
}
template<class T> ostream& operator<<(ostream &out, ordered_set<T> const& S){
    out << "{ ";
    for(const auto& s:S) out << s << " ";
    return (out << "}");
}
template<class L, class R, class chash = std::hash<L> > ostream& operator << (ostream &out, gp_hash_table<L, R, chash> const& M) {
    out << "{ ";
    for(const auto& m: M) out << "(" << m.first << ":" << m.second << ") ";
    return (out << "}");
}
template<class P, class Q = vector<P>, class R = less<P> > ostream& operator << (ostream& out, priority_queue<P, Q, R> const& M){
    static priority_queue<P, Q, R> U;
    U = M;
    out << "{ ";
    while(!U.empty())
        out << U.top() << " ", U.pop();
    return (out << "}");
}
template<class P> ostream& operator << (ostream& out, queue<P> const& M){
    static queue<P> U;
    U = M;
    out << "{ ";
    while(!U.empty())
        out << U.front() << " ", U.pop();
    return (out << "}");
}
#define TRACE
#ifdef TRACE
    #define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cerr << name << " : " << arg1 << endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ',');
        cerr.write(names, comma - names) << " : " << arg1<<" | ";
        __f(comma+1, args...);
    }
#else
    #define trace(...) 1
#endif

/*/---------------------------RNG----------------------/*/
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int64_t random_long(long long l = LLONG_MIN,long long r = LLONG_MAX){
    uniform_int_distribution<int64_t> generator(l,r);
    return generator(rng);
}
struct custom_hash { // Credits: https://codeforces.com/blog/entry/62393
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    template<typename L, typename R>
    size_t operator()(pair<L,R> const& Y) const{
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(Y.first * 31ull + Y.second + FIXED_RANDOM);
    }
};

/*/---------------------------Defines----------------------/*/
#define ll long long
#define endl "\n"
#define all(v) (v).begin(),(v).end()
/*/-----------------------Modular Arithmetic---------------/*/
int mod = 1e9 + 7;

/*/-----------------------------Code begins----------------------------------/*/
const int N = 505;
long long dp[N][(N * N)/2];

long long add(long long x, long long y){
	x += y;
	if (x >= mod)
		return x - mod;
	return x;
}
long long sub(long long x, long long y){
	x -= y;
	if (x < 0)
		return x + mod;
	return x;
}
void preprocess(int n){

	dp[0][0] = 1;
	for(int i = 1; i <= n; ++i){
		long long ub = (i * (i - 1)) >> 1;
		long long psum = 0;
		for(int j = 0; j <= ub; ++j){
			psum = add(psum, dp[i - 1][j]);
			if (j > (i - 1)){
				psum = sub(psum, dp[i - 1][j - i]);
			}
			dp[i][j] = psum;
		}
	}
}

long long norm(long long x){
	x %= mod;
	if (x < 0)
		x += mod;
	return x;
}
void solve(){

	int M, mod;
	cin >> M >> mod;
	if (mod == 1){
		cout << 0 << endl;
		return;
	}

	auto cnt_inv = [&] (const vector<int>& a){
		int ret = 0;
		for(int i = 0; i < (int)a.size(); ++i){
			for(int j = i + 1; j < (int)a.size(); ++j){
				if (a[j] < a[i]){
					++ret;
				}
			}
		}
		return ret;
	};
	auto calc = [&] (int n){
		vector<pair<vector<int>, int>> perms;

		vector<int> cur(n);
		for(int i = 0; i < n; ++i){
			cur[i] = i;
		}

		do{
			perms.push_back({cur, cnt_inv(cur)});
		}while(next_permutation(all(cur)));
		sort(all(perms));

		long long x = 0;
		for(int i = 0; i < (int)perms.size(); ++i){
			for(int j = i + 1; j < (int)perms.size(); ++j){
				if (perms[i].second > perms[j].second){
					++x;
					if (perms[i].first[0] == perms[j].first[0]){
						// trace(perms[i].first, perms[j].first);
					}
				}
			}
		}
		return x;
	};
	preprocess(M);

	vector<long long> ans(M + 1);

	for(int n = 4; n <= M; ++n){
		int ub = ((n - 1) * n) / 2;
		vector<long long> use;
		for(int z = 0; z <= ub; ++z){
			use.push_back(dp[n - 1][z]);
		}
		vector<int> p0(ub + 1), p1(ub + 1), p2(ub + 1);

		for(int z = 0; z <= ub; ++z){
			long long tmp = (z * (z - 1)) / 2;
			tmp *= use[z];
			p2[z] = tmp % mod;
			tmp = z * use[z];
			p1[z] = tmp % mod;
			p0[z] = use[z];
			if (z > 0){
				p0[z] = add(p0[z - 1], p0[z]);
				p1[z] = add(p1[z - 1], p1[z]);
				p2[z] = add(p2[z - 1], p2[z]);
			}
		}

		for(int j = 0; j < ub; ++j){
			long long cur = use[j];
			long long j_ub = min(j + n, ub);
			long long contribution = 0;

			if (j_ub < ub){
				contribution = ((n * 1LL * (n - 1)) / 2) * 1LL * (p0[ub] - p0[j_ub]);
				contribution = norm(contribution);
			}
			long long t1 = (j * 1LL * (j + 1)) / 2;
			contribution -= (p2[j_ub] - p2[j + 1]) + (t1 * (p0[j_ub] - p0[j + 1])) - (j * 1LL * (p1[j_ub] - p1[j + 1]));
			contribution = norm(contribution);
			contribution += (p1[j_ub] - p1[j + 1]) * 1LL * n;
			contribution -= (p0[j_ub] - p0[j + 1]) * 1LL * n * 1LL * (j + 1);
			ans[n] = add(ans[n], norm(contribution * cur));
		}

	}

	int ret = 0;

	long long mult = 1;

	for(int i = M; i >= 1; --i){
		ret = add(ret, norm(ans[i] * mult));
		mult = (mult * i) % mod;
	}
	cout << ret << endl;

}
int main(){
    // Use "set_name".max_load_factor(0.25);"set_name".reserve(512); with unordered set
    // Or use gp_hash_table<X,null_type>
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cout << fixed << setprecision(25);
    cerr << fixed << setprecision(10);
    auto start = std::chrono::high_resolution_clock::now();

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }

    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
    // cerr << "Time taken : " << ((long double)duration.count())/((long double) 1e9) <<"s "<< endl;
}

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+13;
int dp[maxn],f[maxn],h[maxn];
int main(){
	int n,mod;
	scanf("%d%d",&n,&mod);
	dp[0]=1;
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=1ll*ans*i%mod;
		for(int j=0;j<=i*(i-1)/2;j++){
			f[j]=((j?f[j-1]:0)+dp[j])%mod;
			h[j]=((j?h[j-1]:0)+f[j])%mod;
		}
		int sum=0;
		for(int j=0;j<=i*(i-1)/2;j++){
			if(j>=2) sum=(sum+1ll*f[j-2]*i%mod)%mod;
			if(j>=2) sum=(sum-h[j-2]+mod+(j-i-2>=0? h[j-i-2] : 0))%mod;
			ans=(ans+1ll*sum*dp[j]%mod)%mod;
		}
		for(int j=0;j<=i*(i-1)/2;j++){
			dp[j]=(f[j]-(j-i>=0?f[j-i]:0)+mod)%mod;
		}
	}
	printf("%d",ans);
}

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int n, mod;
    cin >> n >> mod;

    vector<vector<int>> b = vector<vector<int>>(n+1,vector<int>((n*(n-1))/2+1,0));
    vector<vector<int>> c = vector<vector<int>>(n+1,vector<int>((n*(n-1))/2+1,0));

    b[1][0] = 1;
    c[1][0] = 1;

    int prevTotal = 0;
    int total = 0;
    for (int i=2; i<=n; i++) {
        prevTotal=total;
        total = total+i-1;
        for (int j=0; j<=total; j++) {
            int up = j>prevTotal ? c[i-1][prevTotal] : c[i-1][j];
            int down = j-i<0 ? 0 : c[i-1][j-i];
            b[i][j] = (up-down + mod)%mod;
            c[i][j] = j==0 ? b[i][j] : (c[i][j-1] + b[i][j])%mod;
        }
    }

    /*
    for (int i=0; i<=n; i++) {
        for (int j=0; j<=(n*(n-1))/2; j++) {
            cout << b[i][j] << '\t';
        }
        cout << '\n';
    }
    cout << '\n';
    for (int i=0; i<=n; i++) {
        for (int j=0; j<=(n*(n-1))/2; j++) {
            cout << c[i][j] << '\t';
        }
        cout << '\n';
    }
    */

    vector<long long> factorials = vector<long long>(n+1,1);
    for (long long i=1; i<=n; i++) {
        factorials[i] = (factorials[i-1]*i)%mod;
    }

    long long count = 0;
    prevTotal=0;
    total = 0;
    for (int i=2; i<=n; i++) {
        prevTotal = total;
        total = total+i-1;
        for (int j=0; j<=total; j++) {
            long long accum=0;
            for (int k=1; k<=min(i,j+1); k++) {
                int low = j-k+2>prevTotal ? c[i-1][prevTotal] : c[i-1][j-k+2];
                long long next = k==1 ? 0 : ((long long)c[i-1][prevTotal] - low + mod)%mod;
                accum = (accum+next)%mod;
                int up = j-k+1>prevTotal ? c[i-1][prevTotal] : c[i-1][j-k+1];
                int down = j-k>prevTotal ? c[i-1][prevTotal] : c[i-1][j-k];
                long long a = ((long long)up-down + mod)%mod;
                count = (count + a*accum)%mod;

                cout << i << ' ' << j << ' ' << k << ' ' << accum << ' ' << count << ' ' << a <<
                    ' '<< up << ' ' << down << '\n';
            }
        }
    }
    cout << count << '\n';
}

// EXPLOSION!
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#include<chrono>

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<pair<int, int>> vpi;
typedef vector<pair<ll, ll>> vpll;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define mp make_pair
#define rsz resize
#define sz(x) int(x.size())
#define all(x) x.begin(),x.end()
#define f first
#define s second
#define cont continue
#define endl '\n'
//#define ednl '\n'
#define test int testc;cin>>testc;while(testc--)
#define pr(a, b) trav(x,a)cerr << x << b; cerr << endl;
#define message cout << "Hello World" << endl;
const int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 }; // for every grid problem!!
const ll linf = 4000000000000000000LL;
const ll inf = 998244353;//    1000000007

void pv(vi a) { trav(x, a)cout << x << " "; cout << endl; }void pv(vll a) { trav(x, a)cout << x << " "; cout << endl; }void pv(vector<vi>a) {
	F0R(i, sz(a)) { cout << i << endl; pv(a[i]); cout << endl; }
}void pv(vector<vll>a) { F0R(i, sz(a)) { cout << i << endl; pv(a[i]); }cout << endl; }void pv(vector<string>a) { trav(x, a)cout << x << endl; cout << endl; }
void setIO(string s) {
	ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef arwaeystoamneg
	if (sz(s))
	{
		freopen((s + ".in").c_str(), "r", stdin);
		if (s != "test1")
			freopen((s + ".out").c_str(), "w", stdout);
	}
#endif
}
int n, m;
struct mi
{
	int x;
	mi()
	{
		x = 0;
	}
	mi(int y)
	{
		x = y;
	}
	mi operator+(const mi& y)const
	{
		return (x + y.x) % m;
	}
	void operator+=(const mi& y)
	{
		x = x + y.x;
	}
	mi operator* (const mi& y)const
	{
		return ((ll)x * y.x) % m;
	}
};
int main()
{
	setIO("test1");
	cin >> n >> m;
	int zero = n * n + 5;
	vector<vector<mi>>dp(n + 1, vector<mi>(2 * zero));
	fill(dp[n].begin(), dp[n].begin() + zero, 1);
	R0F(i, n)
	{
		F0R(j, 2 * zero)
		{
			F0R(k, n - i)
			{
				F0R(l, n - i)
				{
					if (j + k - l >= 0 && j + k - l < 2 * zero)
						dp[i][j] += dp[i + 1][j + k - l];
				}
			}
		}
	}
	vector<mi>c(n + 1);
	c[n] = 1;
	R0F(i, n)c[i] = c[i + 1] * (i + 1);
	reverse(all(c));
	mi ans;
	// length of the longest prefix common
	FOR(len, 2, n + 1)
	{
		F0R(j, len)
		{
			F0R(k, j)
			{
				ans += dp[n - len + 1][j - k + zero] * c[n - len];
			}
		}
	}
	cout << ans.x << endl;
}

/*
fi 表示长度为i的排列，p<q且逆序对数p>q的方案数
gij 表示长度为i的排列，任意放，使得p逆序对数比q多j的方案数

f[n] = \sum A_{n,i} * f[n - i] +
g[i][j] =
*/

#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s^'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T t = 0 , tmp[25] = {};
	while(x) tmp[t ++] = x % 10 , x /= 10;
	while(t -- > 0) putchar(tmp[t] + '0');
	putchar(s);
}

const int N = 1250;

LL n , mod , f[55] , g[55][55 * 55] , A[55][55] , tmp[55 * 55];

void Add(LL &x , LL y) {x = (x + y + mod) % mod;}

int main() {
	read(n),read(mod);
	g[2][1251] = 1;
	g[2][1250] = 2;
	g[2][1249] = 1;
	for (int i = 3; i <= n; ++i) {
		Add(f[i] , i * f[i - 1] % mod);
		for (int j = N - (i - 1) * i / 2; j <= N + i * (i - 1) / 2; ++j) {
			for (int k = 1; k < i; ++k) {
				if(j - k >= 0) Add(g[i][j] , g[i - 1][j - k] * (i - k) % mod);
				if(j + k <= N * 2) Add(g[i][j] , g[i - 1][j + k] * (i - k) % mod);
			}
			Add(g[i][j] , g[i - 1][j] * i % mod);
		}
		tmp[0] = 0;
		for (int j = 1; j <= i * (i - 1) / 2; ++j) tmp[j] = g[i - 1][N + j] , Add(tmp[j] , tmp[j - 1]);
		for (int j = 1; j < i; ++j)
			Add(f[i] , (tmp[i * (i - 1) / 2] - tmp[j]) * (i - j) % mod);
	}
	write(f[4]);
	return 0;
}

#include <bits/stdc++.h>
#define N 200005
#define fi first
#define sc second

using namespace std;
typedef pair<int, int> II;

int length , mod;

int answer[N] , first_dif[N];
int dynamic[55][N];
int sums_dynamic[55][N];

void solve()
{
    int limit_int = length * (length - 1)/2;

    for(int i = 1; i <= length; i++){
        dynamic[i][0] = 1;
        for(int j =1 , lim = i * (i-1)/2 ;j <= lim; j++){

            for(int fir = 1 , fir_lim = min( i , j+1 ) ; fir <= fir_lim ; fir++)
                dynamic[i][j] = ( dynamic[i][j] +  dynamic[i-1][j - ( fir - 1 ) ] ) % mod;
        }
    }

    for(int i =1 ;i <= length; i++){
        sums_dynamic[i][0] = 1;
        for(int j = 1, lim = i * (i-1)/2; j <= lim; j++)
            sums_dynamic[i][j] = sums_dynamic[i][j-1] + dynamic[i][j];
    }

    int run_count = 0;

    for(int i = 2;i <= length; i++){

        for(int fir = 1; fir < i; fir++)
        for(int sec = fir +1 ; sec <= i ; sec++)
            for(int total_int = 0, cur_lim = i * (i-1)/2 ; total_int <= cur_lim; total_int++){

                if( total_int - fir + 1 >= 0 )
                if( total_int - sec >= 0 )

                first_dif[i] = ( first_dif[i] + (long long)dynamic[i-1][total_int - fir + 1 ] * sums_dynamic[i-1][ total_int - sec ] % mod )%mod;
            }
    }

    for(int i =1 ;i <= length; i++)
        answer[i] = ( (long long)i * answer[i-1] + first_dif[i] ) % mod;

    printf("%d", answer[length] );
}

int main()
{
    // freopen("main.inp", "r", stdin );

    scanf("%d %d", &length , &mod );
    solve();
}

/// Fuck Them, Fuck Me, and Fuck You
#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;

#include "bits/stdc++.h"
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>

using namespace __gnu_pbds;
using namespace __gnu_cxx;

using ll = long long;
using ii = pair<int, int>;

typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

#define pb push_back
#define F first
#define S second
#define f(i, a, b)  for(int i = a; i < b; i++)
#define all(a)  a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

const int N = 1e6 + 5, LG = 19, MOD = 998244353;
ll dp[55][55*55];
int n;
int C[55][55];
int M;
ll solve(int n, int inv1, int inv2) {
    if(!n){
        return inv1 > inv2;
    }
    ll &ret = dp[n][inv1-inv2+1500];
    if(~ret)
        return ret;
    ret = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            ret += solve(n-1,inv1 + i, inv2 + j);
    return ret;
}
void doWork() {
    cin >> n >> M;
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= i; j++) {
            if(j==0||i==j){
                C[i][j] = 1;
            }   else {
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % M;
            }
        }
    memset(dp,-1,sizeof dp);
    ll ans = 0;
    for(int lcp = 0; lcp < n; lcp++) {
        ll sum = 0;
        for(int i = 0; i < n - lcp; i++)
            for(int j = i + 1; j < n - lcp; j++) {
                sum += solve(n - lcp - 1, i, j);
            }
        ans = (ans + sum * C[n][lcp]) % M;
    }

    cout << ans << '\n';

}

int32_t main() {
#ifdef ONLINE_JUDGE
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif // ONLINE_JUDGE

    int t = 1;
//    cin >> t;

    while (t--) {
        doWork();
    }

    return 0;
}

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define MOD2 1000000007
//#define MOD 998244353
#define pb push_back
#define pf push_front
#define mp make_pair
#define mt make_tuple
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define ll long long
#define int long long
#define sz(a) (int)((a).size())
#define num_bits(a) __builtin_popcountll(a)
using namespace std;
using namespace __gnu_pbds;

int dp[51][1226]; //Number of permutations, length i, with j inversions.
int pre[51][1226];
int mod;
ll fact[51];
void f()
{
    int MAXN=50;
    fact[0]=1;
    fact[1]=1;
    for(int i=2;i<=MAXN;i++)
    {
        fact[i]=(fact[i-1]*i)%mod;
    }

}

int32_t main()
{
    int n; cin>>n>>mod;
    f();
    dp[1][0]=1;
    pre[1][0]=1;
    for (int i=1; i<n; i++) {
        for (int j=0; j<=(i-1)*(i)/2; j++) {
            for (int k=0; k<=i; k++) {
                dp[i+1][j+k]+=dp[i][j];
                dp[i+1][j+k]%=mod;
            }
            if (j==0) {
                pre[i][j]=dp[i][j];
            }
            else {
                pre[i][j]=pre[i-1][j]+dp[i][j];
                pre[i][j]%=mod;
            }
        }
    }
    int ans=0;
    for (int i=n-1; i>=0; i--) {
        //i: number present later.
        int nw=fact[n-1-i];
        for (int diff=1; diff<=i; diff++) {
            int temp=0;
            for (int j=0; j+diff+1<=(i-1)*(i)/2; j++) {
                temp+=(pre[i][j]*dp[i][j+diff+1]);
                temp%=mod;
            }
            temp*=nw; temp%=mod;
            //number of times diff occurs?
            temp*=(i-diff+1); temp%=mod;
            ans+=temp; ans%=mod;
        }
    }
    cout<<ans<<endl;

    return 0;
}

/*
//Common Mistakes:
1. Using set instead of multi set.
2. non-void function should always return something (or else RTE or TLE).
3. Erasing from set while iterating it.
*/

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int O = 1e2 + 5;

int n, mod, C[O][O], f[O][O], dp[O][O][O], g[O][O], sum[O][O], t[O];

void Add(int &x, int y){
    x += y; x %= mod;
}

main(){
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> mod;
    C[0][0] = 1;
    for (int i = 0; i <= n; ++ i){
        for (int j = 0; j <= n; ++ j){
            Add(C[i + 1][j + 1], C[i][j]);
            Add(C[i][j + 1], C[i][j]);
        }
    }

    for (int i = 1; i <= n; ++ i) t[i] = t[i - 1] + i;

    dp[0][0][0] = 1;
    for (int i = 1; i <= n; ++ i){
        for (int j = 1; j <= i; ++ j){
            for (int z = 0; z <= t[i - 1]; ++ z){
                if (i - j > z) continue;
                for (int l = 0; l <= i - 1; ++ l){
                    Add(dp[i][j][z], dp[i - 1][l][z - i + j]);
                }
            }
        }
    }

    for (int i = 1; i <= n; ++ i){
        for (int j = 0; j <= t[i - 1]; ++ j){
            for (int z = 0; z <= i; ++ z){
                Add(g[i][j], dp[i][z][j]);
            }
        }
    }

    for (int i = 1; i <= n; ++ i){
        for (int j = 0; j <= t[i - 1]; ++ j){
            sum[i][j] = g[i][j];
            if (j) Add(sum[i][j], sum[i][j - 1]);
        }
    }

    for (int i = 1; i <= n; ++ i){
        for (int j = 1; j < n - i + 1; ++ j){
            for (int l = j + 1; l <= n - i + 1; ++ l){
                int all = n - i;
                int kc = l - j;
                for (int z = kc + 1; z <= t[all - 1]; ++ z){
                    Add(f[i][j], g[all][z] * sum[all][z - kc - 1] % mod);
                }
            }
        }
    }

    int ans = 0;
    for (int i = 1; i <= n; ++ i){
        for (int j = 1; j < n - i + 1; ++ j) Add(ans, f[i][j]);
    }
    cout << ans;
}

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <iostream>
#include <cstring>
#include <bitset>
#include <ctime>
#include <functional>

typedef long long LL;
typedef unsigned long long uLL;

int read() {
    int s = 0,w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

LL readl() {
    LL s = 0,w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

///////////////////////////////////// wanna become a master

int MOD;
int n;
const int maxn = 55;
const int maxr = 2500;
std::vector<int> vec[maxn];
int vis[maxn];
int cnt[maxn];
LL dp[maxn][maxr + 5];
LL C[maxn][maxn];

LL fpow(LL a, LL b) {
    LL ret = 1;
    while (b) {
        if (b & 1) ret = ret * a % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return ret;
}

void init() {
    C[1][0] = C[1][1] = 1;
    for (int i = 2 ; i < maxn ; i++ ) {
        C[i][0] = 1;
        for (int j = 1 ; j <= i ; j++ ) {
            C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
            C[i][j] %= MOD;
        }
    }
}

int main() {
    n = read();
    MOD = read();
    init();
    dp[1][0] = 1;
    for (int i = 2 ; i <= n ; i++ ) {
        for (int j = 0 ; j <= maxr ; j++ ) {
            for (int k = 0 ; k < i && j - k >= 0 ; k++ ) {
                dp[i][j] += dp[i - 1][j - k];
                dp[i][j] %= MOD;
            }
        }
    }
    // for (int i = 0 ; i <= 30 ; i++ ) {
    //     printf("[%d, %d] = %lld\n", 4, i, dp[4][i]);
    // }
    LL ans = 0;
    for (int i = 1 ; i < n ; i++ ) {
        LL tmp = C[n][i - 1];
        int left = n - i + 1;
        LL c = 0;
        for (int p = 1 ; p < left ; p++ ) {
            for (int q = p + 1 ; q <= left ; q++ ) {
                int a = p - 1;
                int b = q - 1;
                LL low = 0;
                int lim = C[left - 1][2];
                for (int inv = b + 1 - a ; inv <= lim ; inv++ ) {
                    low += dp[left - 1][inv + a - b - 1];
                    low %= MOD;
                    c += low * dp[left - 1][inv] % MOD;
                    c %= MOD;
                }
            }
        }
        ans += tmp * c % MOD;
        ans %= MOD;
    }
    printf("%lld\n", ans);
    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <string.h>

using namespace std;

#define ll long long
#define ull unsigned long long
const int maxn = 55;
int mod;
int dp[maxn][maxn * maxn];
int C[maxn][maxn];
int main() {
    int n;scanf("%d%d", &n, &mod);
    dp[1][0] = 1;
    for(int i = 2; i <= n; i++) {
        for(int j = 0; j <= i * i; j++) {
            if(dp[i-1][j]) {
                for(int k = 0; k <= i - 1; k++) {
                    dp[i][j + k] = (dp[i][j + k] + dp[i-1][j]) % mod;
                }
            }
        }
    }

    C[0][0] = 1;
    for(int i = 1; i <= n; i++) {
        C[i][0] = 1;
        for(int j = 1; j <= i; j++) {
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % mod;
        }
    }

    int ans = 0;
    for(int i = n; i > 1; i--) {
        for(int x = 1; x < i; x++) {
            for(int y = x + 1; y <= i; y++) {
                int u = 1LL * C[n][i] * C[n][i] % mod;
                int s[maxn*maxn];
                memset(s, 0, sizeof(s));
                s[0] = dp[i-1][0];
                for(int j = 1; j <= i * i; j++) {
                    s[j] = (s[j-1] + dp[i-1][j]) % mod;
                }
                for(int j = 0; j <= i * i; j++) {
                    int v = x - 1 + j;
                    if(v - (y - 1) > 0) {
                        ans = (ans + 1LL * dp[i-1][j] * s[v - y] % mod * u % mod) % mod;
                    }
                }
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

#include <cmath>
#include <cassert>
#include <iostream>
#include <set>
#include <climits>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <type_traits>
#include <string>
#include <queue>
#include <map>

using namespace std;
int N;
int M;
struct modint {
    modint() : n(0) {}
    template <class T> modint(T n) { n %= M; if (n < 0) n += M; this->n = n; }

    modint & operator+=(const modint &r) { n += r.n; if (n >= M) n -= M; return *this; }
    modint & operator-=(const modint &r) { n -= r.n; if (n < 0) n += M; return *this; }
    modint & operator*=(const modint &r) { n = (int) ((long long) n * r.n % M); return *this; }

    modint & operator--() { if (--n == -1) n = M - 1; return *this; }
    modint & operator++() { if (++n == M) n = 0; return *this; }
    modint operator--(int) { modint t = *this; --*this; return t; }
    modint operator++(int) { modint t = *this; ++*this; return t; }

    modint operator-() const { return 0 - *this; }
    modint operator+() const { return *this; }

    modint pow(long long k = M - 2) const {
        modint f = *this, p = 1;
        while (k > 0) {
            if (k % 2 == 1) f *= p;
            p *= p, k /= 2;
        }
        return f;
    }

    int mod() const { return M; }

    friend modint operator+(modint l, const modint &r) { return l += r; }
    friend modint operator-(modint l, const modint &r) { return l -= r; }
    friend modint operator*(modint l, const modint &r) { return l *= r; }

    friend bool operator==(const modint &l, const modint &r) { return l.n == r.n; }
    friend bool operator!=(const modint &l, const modint &r) { return l.n != r.n; }

    friend ostream & operator<<(ostream &out, const modint &r) { return out << r.n; }

    int n;
};

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> N >> M;
    vector<vector<modint>> combo(N + 1);
    for (int i = 0; i <= N; i++) {
    	combo[i].assign(N + 1, 0);
    }
    for (int i = 0; i <= N; i++) {
    	for (int j = 0; j <= N; j++) {
    		if (i < j) {
    			combo[i][j] = 0;
    			continue;
    		}
    		if (j == 0) {
    			combo[i][j] = 1;
    			continue;
    		}
    		combo[i][j] = combo[i - 1][j - 1] + combo[i - 1][j];
    	}
    }
    const int offset = N * (N - 1)/2;
    vector<vector<modint>> dp(N + 1);
    for (int i = 0; i < dp.size(); i++) {
    	dp[i].assign(N * N + 1, 0);
    }
    dp[1][offset] = 1;
    for (int n = 2; n <= N; n++) {
    	for (int k = 0; k < (int)dp[n].size(); k++) {
    		dp[n][k] = 0;
    		for (int x = - (n - 1); x <= n - 1; x++) {
    			if (k - x >= 0 && k - x < (int)dp[n - 1].size()) {
    				dp[n][k] += dp[n - 1][k - x] * (n - abs(x));
	    		}
    		}
    	}
    }
    vector<modint> ans;
    ans.assign(N * N + 1, 0);
    for (int len = 0; len <= N - 1; len++) {
    	for (int p = 0; p < N - len; p++) {
    		for (int q = p + 1; q < N - len; q++) {
    			for (int inv = 0; inv < dp[N].size(); inv++) {
    				if (inv + (q - p) >= 0 && inv + (q - p) < dp[N].size()) {
    					ans[inv] = ans[inv] + dp[N - len - 1][inv + (q - p)] * combo[N][len];
    				}
    			}
    		}
    	}
    }
    modint res = 0;
    for (int i = offset + 1; i < ans.size(); i++) {
    	res += ans[i];
    }
    cout << res << '\n';
}

#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 53;

int n, M;

int c[N][N];

int dp0[N][N * N];
int p[N][N * N];

void solv()
{
    cin >> n >> M;

    for (int i = 0; i <= n; ++i)
    {
        c[i][0] = 1;
        for (int j = 1; j <= i; ++j)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M;
    }

    for (int i = 1; i <= n; ++i)
    {
        if (i == 1)
            dp0[i][0] = 1;
        else
        {
            dp0[i][0] = 1;
            for (int j = 1; j <= n * n; ++j)
            {
                dp0[i][j] = (dp0[i - 1][j] + dp0[i][j - 1]) % M;
                if (j - i >= 0)
                    dp0[i][j] = (dp0[i][j] - dp0[i - 1][j - i] + M) % M;
            }
        }

        p[i][0] = dp0[i][0];
        for (int j = 1; j <= n * n; ++j)
            p[i][j] = (p[i][j - 1] + dp0[i][j]) % M;
    }

    int ans = 0;
    for (int i = 1; i <= n; ++i)
    {
        for (int x = 1; x <= n - (i - 1); ++x)
        {
            for (int y = x + 1; y <= n - (i - 1); ++y)
            {
                int yans = 0;
                for (int q = 0; q <= n * n; ++q)
                {
                    int u = x - 1 - (y - 1) + q;
                    if (u > 0)
                        yans = (yans + dp0[n - i][q] * 1LL * p[n - i][u - 1]) % M;
                }
                yans = (yans * 1LL * c[n - 2][i - 1]) % M;
                ans = (ans + yans) % M;
            }
        }
    }

    cout << ans << "\n";
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    ios_base::sync_with_stdio(false), cin.tie(0);

    int tt = 1;
    //cin >> tt;
    while (tt--)
    {
        solv();
    }
    return 0;
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author
 */

#include <iostream>
#include <fstream>

#ifndef PRELUDE_H
#define PRELUDE_H

#define M_PI 3.14159265358979323846
#define EPS 1e-9

#include <algorithm>
#include <cmath>
#include <numeric>

#include <vector>
#include <set>
#include <map>
#include <queue>

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

typedef std::pair<int, int> ii;
typedef std::pair<ll, ll> llll;
typedef std::pair<int, ll> ill;
typedef std::pair<double, double> dd;

typedef std::vector<int> vi;
typedef std::vector<ii> vii;
typedef std::vector<vi> vvi;
typedef std::vector<vvi> vvvi;
typedef std::vector<vii> vvii;
typedef std::vector<ill> vill;
typedef std::vector<vill> vvill;

typedef std::vector<bool> vb;

typedef std::vector<char> vc;
typedef std::vector<std::vector<char>> vvc;

typedef std::vector<ll> vll;
typedef std::vector<vll> vvll;
typedef std::vector<llll> vllll;
typedef std::vector<double> vd;
typedef std::vector<dd> vdd;

typedef std::string ss;
typedef std::vector<ss> vss;
typedef std::vector<vss> vvss;

typedef std::set<int> si;
typedef std::set<ii> sii;
typedef std::set<ll> sll;

typedef std::map<int, int> mii;
typedef std::map<char, int> mci;

typedef std::queue<int> qi;

typedef std::vector<std::pair<int, ii>> EdgeList;

#define REP(i,n) for(int i=0;i<n;++i)
#define DEBUG(a) #a << ": " << (a) << " " <<
#define ENDL "\n"
#define REPLL(l,n) for(ll l=0;l<n;++l)
#define FOR(i,s,n) for(int i=s;i<=n;++i)
#define FOREACH(it,a) for(auto it=a.begin(); it != a.end(); ++it)

#endif //PRELUDE_H

class E1AbnormalPermutationPairsEasyVersion {
public:
    void solve(std::istream& in, std::ostream& out) {
        int n; ll mod;
        in >> n >> mod;
        int maxinv = n * (n-1) / 2;
        vvll dp(n+1, vll(maxinv+1));
        dp[0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int inv = 0; inv <= i * (i-1) / 2; ++inv) {
                // choose pos for i
                for (int ipos = 0; ipos < i; ++ipos) {
                    int fixedInv = i-1-ipos;
                    if (fixedInv > inv) {
                        continue;
                    }
                    ll add = dp[i-1][inv-fixedInv];
                    dp[i][inv] = (dp[i][inv] + add) % mod;
                }
            }
        }
        vvll dpsuf(n+1, vll(n*(n-1)/2+1));
        for (int i = 1; i <= n; ++i) {
            dpsuf[i][i*(i-1)/2] = dp[i][i*(i-1)/2];
            for (int inv = i * (i-1) / 2 - 1; inv >= 0; inv--) {
                dpsuf[i][inv] = (dp[i][inv] + dpsuf[i][inv+1]) % mod;
            }
        }
        vll ans(n+1);
        ans[1] = ans[2] = 0;
        for (int i = 3; i <= n; ++i) {
            ll an = ans[i-1] * n % mod; // samish
            for (int smol = 1; smol <= i; ++smol) {
                for (int lar = smol+1; lar <= i; ++lar) {
                    // p smol q lar
                    int overhead = lar - smol;
                    // p needs overhead + 1 inversions at least more than q
                    for (int qinv = 0; qinv + overhead + 1 <= (i-1) * (i-2) / 2; ++ qinv) {
                        ll add = dp[i-1][qinv] * dpsuf[i-1][qinv + overhead + 1] % mod;
                        an += add;
                        an %= mod;
                    }
                }
            }
            ans[i] = an;
        }
        out << ans[n];
    }
};

int main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout << std::fixed;
	std::cout << std::setprecision(15);

	E1AbnormalPermutationPairsEasyVersion solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}

#include <iostream>
#include <cmath>
#include <utility>

using namespace std;

#define mp make_pair
#define x first
#define y second
typedef pair<int,int> pii;
typedef long long ll;

ll dp[55][55][2505],sum[55][2505],suff[55][2505],C[55][55];
int mod;

ll add(ll x,ll y){
	if(x+y>mod-1) return x+y-mod;
	return x+y;
}
ll mult(ll x,ll y){
	return x*y%mod;
}

void invprep(){
	dp[1][1][0]=1ll;
	sum[1][0]=1ll;
	for(int i=2;i<=50;i++){
		for(int j=1;j<=i;j++){
			for(int k=0;k<=i*i/2;k++){
				dp[i][j][k]=sum[i-1][k-j+1];
			}
		}
		for(int k=0;k<=i*i/2;k++){
			for(int j=1;j<=i;j++){
				sum[i][k]=add(sum[i][k],dp[i][j][k]);
			}
		}
	}
}
void coefprep(){
	C[1][0]=1ll;
	C[1][1]=1ll;
	for(int i=2;i<=50;i++){
		for(int j=0;j<=i;j++){
			C[i][j]=add(C[i-1][j],C[i-1][j-1]);
		}
	}
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin>>n;
	cin>>mod;
	invprep();
	for(int i=1;i<=n;i++){
		for(int j=i*i/2;j>=0;j--){
			suff[i][j]=add(suff[i][j+1],sum[i][j]);
		}
	}
	coefprep();
	ll sol=0ll;
	ll temp;
	ll mn;
	ll fakt,suma;
	for(int i=0;i<n-2;i++){
		mn=C[n][i];
		suma=0ll;
		for(int j=1;j<n-i;j++){
			temp=n-i-j;
			fakt=0ll;
			for(ll k=0;k<n*n/2;k++){
				fakt=add(fakt,mult(sum[n-i-1][k],suff[n-i-1][k+j+1]));
			}
			suma=add(suma,mult(fakt,temp));
		}
		sol=add(sol,mult(mn,suma));
	}
	cout<<sol;

return 0;
}

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <list>
#include <cassert>
#include <climits>
#include <bitset>
#include <chrono>
#include <random>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
std::mt19937 rnd((int)std::chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 50;

int n, MOD;
void inc(int& a, int b) { if ((a += b) >= MOD) a -= MOD; }

vector<int> ways[MAXN + 1];
vector<int> sumways[MAXN + 1];

int choose[MAXN + 1][MAXN + 1];
int fac[MAXN + 1];

int solve() {
	/*{
		int want = 0;
		vector<int> p(n); REP(i, n) p[i] = i;
		auto calcinv = [&](vector<int>& a) { int ret = 0; REP(i, n) FOR(j, i + 1, n) if (a[i] > a[j]) ++ret; return ret; };
		do {
			vector<int> q(n); REP(i, n) q[i] = i;
			do {
				if (p >= q) continue;
				if (calcinv(p) <= calcinv(q)) continue;
				//int pref = 0; REP(i, n) if (p[i] == q[i]) ++pref; else break;
				//int diff = q[pref] - p[pref]; REP(i, pref) if (p[i] > p[pref] && p[i] < q[pref]) --diff;
				//REPSZ(i, p) printf(" %d", p[i]); printf(" vs"); REPSZ(i, q) printf(" %d", q[i]); puts("");
				++want;
			} while (next_permutation(q.begin(), q.end()));
		} while (next_permutation(p.begin(), p.end()));
		printf("want=%d\n", want % MOD);
	}*/

	REPE(i, n) { choose[i][0] = choose[i][i] = 1 % MOD; FOR(j, 1, i) choose[i][j] = (choose[i - 1][j - 1] + choose[i - 1][j]) % MOD; }
	fac[0] = 1 % MOD; FORE(i, 1, n) fac[i] = (ll)fac[i - 1] * i % MOD;

	ways[0] = vector<int>(1, 1 % MOD);
	FORE(i, 1, n) {
		ways[i] = vector<int>(i * (i - 1) / 2 + 1, 0);
		REP(j, i) REPSZ(k, ways[i - 1]) inc(ways[i][k + j], ways[i - 1][k]);
	}
	//REPE(i, n) { printf("ways%d:", i); REPSZ(j, ways[i]) printf(" %d", ways[i][j]); puts(""); }

	REPE(i, n) {
		sumways[i] = ways[i];
		FORSZ(j, 1, sumways[i]) inc(sumways[i][j], sumways[i][j - 1]);
	}

	int ret = 0;
	REP(pref, n) {
		FOR(diff, 1, n - pref) {
			int cur = 0;
			REPSZ(k, ways[n - pref - 1]) {
				int lim = k - diff - 1;
				if (lim < 0) continue;
				cur = (cur + (ll)ways[n - pref - 1][k] * sumways[n - pref - 1][lim]);
			}
			//printf("pref=%d diff=%d -> %d\n", pref, diff, cur);
			cur = (ll)cur * (n - pref - diff) % MOD;
			cur = (ll)cur * choose[n][pref] % MOD * fac[pref] % MOD;
			//printf("pref=%d diff=%d -> %d\n", pref, diff, cur);
			inc(ret, cur);
		}
	}
	return ret;
}

void run() {
	scanf("%d%d", &n, &MOD);
	printf("%d\n", solve());
}

int main() {
	run();
	return 0;
}

#include <iostream>

#define int long long

const int MAXN = 505;
const int MAXP = 124755;

int n, MOD;

int numi[MAXN][MAXP];
int ans[MAXN];

signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);

  std::cin >> n >> MOD;

  int maxi[n+1]; // max number of inversions for permuation of i numbers
  for(int i = 1; i <= n; i++)
    maxi[i] = (i*(i-1))/2;

  for(int i = 0; i < MAXP; i++)
    numi[1][i] = 1;

  ans[1] = 0;
  ans[0] = 0;

  for(int i = 2; i <= n; i++) {
    for(int j = 0; j <= maxi[i]; j++) {
      int sub = (j-i >= 0 ? numi[i-1][j-i] : 0);
      numi[i][j] = (numi[i-1][j] - sub + MOD)%MOD;
    }

    for(int j = 1; j < MAXP; j++)
      numi[i][j] = (numi[i][j] + numi[i][j-1])%MOD;
  }

  for(int i = 2; i <= n; i++) {
    int dp0[maxi[i]+1];
    int dp1[maxi[i]+1];
    int dp2[maxi[i]+1];
    int dp3[maxi[i]+1];

    dp0[0] = dp1[0] = dp2[0] = dp3[0] = numi[i][0];
    for(int j = 1; j <= maxi[i]; j++) {
      int end = i;
      int slast = (i*(i+1))/2;
      dp0[j] = (numi[i][j]-numi[i][j-1]+MOD)%MOD;
      dp1[j] = numi[i][j];
      if(j-end >= 0)
        dp1[j] = (dp1[j] + MOD - dp0[j-end])%MOD;
      dp2[j] = (dp2[j-1] + dp1[j])%MOD;
      if(j - end >= 0)
        dp2[j] = (dp2[j] + MOD - (i*dp1[j-end])%MOD)%MOD;
      dp3[j] = (dp3[j-1] + dp2[j])%MOD;
      if(j - end >= 0) {
        int sub = (i*(i+1))/2;
        sub *= dp0[j-i];
        sub %= MOD;
        dp3[j] = (dp3[j] + MOD - sub)%MOD;
      }
    }

    for(int j = 2; j <= maxi[i]; j++) {
      int end = i;
      int slast = (i*(i+1))/2;

      int cur = (i+1)*dp2[j-2];
      cur %= MOD;
      cur += MOD - dp3[j-2];
      cur %= MOD;

      if(j-2-end >= 0) {
        cur += slast*numi[i][j-2-end];
        cur %= MOD;
      }

      ans[i] += dp0[j]*cur;
      ans[i] %= MOD;
    }
  }

  int finale = 0;
  int cur = 1;

  for(int i = 0; i < n; i++) {
    finale += cur*ans[n-i-1];
    finale %= MOD;
    cur = (cur*(n-i))%MOD;
  }

  std::cout << finale << std::endl;

  return 0;
}

/**
*   author : GDA
*   created : 11/02/2021
*
**/
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> //required
#include <ext/pb_ds/tree_policy.hpp> //required
#define pb push_back
#define pf push_front
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define distinct(x) sort((x).begin(),(x).end()); x.resize(unique((x).begin(),(x).end())-x.begin());
#define sz(x)  (long long)(x).size()
#define resz resize
#define Vec vector
#define lowerB lower_bound
#define upperB upper_bound
#define mkp make_pair
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define ms(dp,a) memset(dp,(ll)a,sof(dp))
#define FastIO ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define PRECISION(n) std::cout.unsetf ( std::ios::floatfield );std::cout.precision((long long)n)
#define getsm(v) accumulate(all(v),0ll)
#define getmx(v) max_element(all(v))
#define getmn(v) min_element(all(v))
#define ws1(a) cout<<(a)<<" "
#define wr1(a) cout<<(a)<<endl
#define wr2(a,b) cout<<(a)<<" "<<(b)<<endl
#define wr3(a,b,c) cout<<(a)<<" "<<(b)<<" "<<(c)<<endl
#define wr4(a,b,c,d) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<endl
#define ww1(a) cout<<(a)<<"\n"
#define ww2(a,b) cout<<(a)<<" "<<(b)<<"\n"
#define ww3(a,b,c) cout<<(a)<<" "<<(b)<<" "<<(c)<<"\n"
#define ww4(a,b,c,d) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<"\n"
#define FileIO freopen("input.txt","r",stdin);freopen("output.txt","w",stdout)
#define PI 3.14159265358979323846264338327950288419716939937510
#define fi first
#define se second
#define here cout<<"RSSB"<<endl
#define dbg cout<<"Krishna"<<endl
#define showzero cout<<std::showpoint
#define bitcount( x ) (int)__builtin_popcountll( x )
#define ls(i) (1ll<<(i))
using namespace __gnu_pbds; //required
using namespace  std ;
#define int long long
typedef vector<int>vi ;
typedef vector<int>vll ;
typedef vector<vector<int> >vvl ;
typedef pair<int,int> pll ;
typedef vector<pll>vpll ;
typedef vector<string>vstr;
typedef vector<bool>vbool ;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <class T = int>
void readArray(vector<T> &v, int n){T a ;for(int i=0 ; i<n ; i=i+1){cin>>a ;v.push_back(a);}}
template <class T = int>
void printArray(vector<T> &v , int a = 0){for(int i=a ; i<v.size() ; i=i+1){/*v[i] = max((int)0,v[i]);*/cout<<v[i]<<" " ;}cout<<"\n" ;}

const int mod  = 1000000007;//Area of mod
// const int mod = 998244353;

int stringToInteger(string str1 , int x = 0){int a,b;b = sz(str1);a = 0;int c = 1;reverse(all(str1));for(int i=0 ; i<b ; i++){a+=(str1[i]-'0')*c;c*=10;if(x){c%=mod;a%=mod;}}return(a);}
string integerToString(int x){string str1 = "";while(x){int c = x%10;str1+=(c+'0');x/=10;}reverse(all(str1));return(str1);}
double logy(int n , int b){if(b==0){return(-1);}if(n==1){return(0);}return((double)log10(n)/(double)log10(b));}
long long power(long long k , long long n , long long m=mod){long long res = 1;while(n){if(n%2!=0){res = (res*k)%m ;}k = (k*k)%m ;n = n/2 ;}return(res) ;}
double powerD(double k , long long n ){double res = 1;while(n){if(n%2!=0){res = (res*k) ;}k = (k*k) ;n = n/2 ;}return(res) ;}
int gcdExtend(int a , int b , int &x , int &y){if(a==0){x = 0;y = 1;return(b);}int x1,y1;int g = gcdExtend(b%a,a,x1,y1);x = y1 - (b/a)*x1;y = x1;return(g);}
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
int lcm(int a, int b) {return((a/gcd(a,b))*b);}
void coordinateCompress(vll &v){vll v1 = v;distinct(v1);for(auto &j : v){j = upperB(all(v1),j) - v1.begin();}}
double distance(pair<double,double> a , pair<double,double> b){return((double)(sqrt( ((a.first-b.first)*(a.first-b.first)) + ((a.second-b.second)*(a.second-b.second)))));}
const int ddx[8] = {-1,1,0,0,-1,1,-1,1};
const int ddy[8] = {0,0,-1,1,-1,-1,1,1};
const int N = 100003;  //N idhar hai
const int M = 300003;  //M idhar hai
const int inf = 1e17;
const int minf = -1e17;
int n,m,k,a1,a2,a3,h,t;
//double prob;
string str,str1,str2;
bool ok = true;
int dp[51][1230];
vll fact(55,1);
void add(int &a , int b)
{
    while(b<0)
    {
        b+=m;
    }
    a = (a%m + b%m)%m;
}
void mul(int &a , int b)
{
    a = (a%m * b%m)%m;
}
void Div(int &a , int b)
{
    mul(a,power(b,a1-1,m));
}
int nck(int a , int b)
{
    int c = fact[a];
    int d = fact[b];
    mul(d,fact[a-b]);
    Div(c,d);
    return(c);
}
int phi(int n) {
    int result = n;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            while (n % i == 0)
                n /= i;
            result -= result / i;
        }
    }
    if (n > 1)
        result -= result / n;
    return result;
}
void solveIt()
{
    //* Check for N <---> Given Constraints(1)
    //* Check For int <---> long long
    int a,b,c,d,i,j,x,y,z,tt;
    double p,q,r,w;
    // string str2;
    char ch;
    // memset(dp,1,sizeof(dp));
    //* Batman has no limits.
    cin>>n>>m;
    a1 = phi(m);
    for(i=2 ; i<55 ; i++)
    {
        fact[i] = (fact[i-1]*i)%m;
    }
    dp[1][0] = 1;
    for(i=2 ; i<=n ; i++)
    {
        int newN = (i*(i-1))/2;
        int ways = 1;
        dp[i][0] = 1;
        for(j=1 ; j<=newN ; j++)
        {
            if(j>=i)
            {
                add(dp[i][j],dp[i-1][j]);
                add(dp[i][j],dp[i][j-1]);
                add(dp[i][j],-dp[i-1][j-i]);
            }
            else
            {
                add(ways,dp[i-1][j]);
                dp[i][j] = ways;
            }
        }
    }
    // for(j=0 ; j<7 ; j++)
    // {
    //     ws1(dp[n][j]);
    // }
    // here;
    int ans = 0;
    for(p=0 ; p<n-1 ; p++)
    {
        int modifiedN = n - p;
        int fixedWays = nck(n,p);
        int tans = 0;
        for(i=1 ; i<=modifiedN ; i++)
        {
            for(j=i+1 ; j<=modifiedN ; j++)
            {
                int scoreFirst = (i-1);
                int scoreSecond = (j-1);
                int scoreDiff = scoreSecond - scoreFirst+1;
                int maxLimit = ((modifiedN-1)*(modifiedN-2))/2;
                int ways = 0;
                for(k = scoreDiff ; k<=maxLimit ; k++)
                {
                    //ans
                    add(ways,dp[modifiedN-1][k-scoreDiff]);
                    int tWays = dp[modifiedN-1][k];
                    mul(tWays,ways);
                    add(tans,tWays);
                }
            }
        }
        mul(tans,fixedWays);
        add(ans,tans);
    }
    ww1(ans);
}
int32_t main()
{
#ifndef ONLINE_JUDGE
       freopen("Rinput.txt", "r", stdin);
       freopen("Routput.txt", "w", stdout);
#endif
    //* SpeakOutLoudWhatYouAreThinkingWhileSolvingQuestion
    //* WhyDoWeFallBruce?
    //* I Don't Ever Give Up-ElonMusk
    //* Zero-ImagineDragons
    //* WorkHardAndSolveProblemAboveYourLevel
    FastIO;
    PRECISION(12);
    //FileIO;
    //Inverse Modulo(for division under mod) = phi(m) - 1 ===> if m is prime then = m-2
    // dr.pb(mkp(0,1));dr.pb(mkp(1,0));dr.pb(mkp(0,-1));dr.pb(mkp(-1,0));
    //For a Graph Problem Sometimes BFS instead of DFS is much helpful
    int t = 1;
    //cin>>t;
    while(t--)
    {
        solveIt();
    }
    // const ll ddx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
    // const ll ddy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
    //WhateverItTakes
    //FOCUS
    //BeABelieverWarrior
    //DO IT UNTIL YOU RUN OUT OF IDEAS ~ YOU KNOW WHO
    //See The Editorial Almost Never ~ YOU KNOW WHO

}

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);

	int n, mod;
	cin >> n >> mod;

	long long cnt_inv[51][1226] = {};
	cnt_inv[1][0] = 1;
	for (int len = 2; len <= 50; len++)
	{
		int U = (len - 1) * (len - 2) / 2;
		for (int val = 0; val <= U; val++)
			for (int a = 0; a < len; a++)
				cnt_inv[len][val + a] += cnt_inv[len - 1][val];

		U += len - 1;
		for (int val = 0; val <= U; val++)
			cnt_inv[len][val] %= mod;
	}
	long long prefix_sum[51][1226] = {};
	for (int len = 0; len <= 50; len++)
	{
		prefix_sum[len][0] = cnt_inv[len][0];
		int U = len * (len - 1) / 2;
		for (int val = 1; val <= U; val++)
			prefix_sum[len][val] = (prefix_sum[len][val - 1] + cnt_inv[len][val]) % mod;
	}

	long long Ans = 0, fact = 1;
	for (int k = n; k > 3; k--)
	{
		long long TEMP = 0;
		int U = (k - 1) * (k - 2) / 2;
		for (int diff_front = 1; diff_front < k; diff_front++)
		{
			long long tmp = 0;
			for (int inv_p = diff_front + 1; inv_p <= U; inv_p++)
				tmp += (cnt_inv[k - 1][inv_p] * prefix_sum[k - 1][inv_p - diff_front - 1]) % mod;
			TEMP += (tmp * (k - diff_front)) % mod;
		}
		Ans = (Ans + TEMP * fact) % mod;
		fact = (fact * k) % mod;
	}
	cout << Ans << '\n';
}

//fast with bitset but not always efficient
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//
#include<bits/stdc++.h>
using namespace std;
int64_t mod,n;
vector<int64_t> fact(55);
int main (){
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n>>mod;
    fact[n+1]=1;
    for (int i=n;i>=0;i--) fact[i]=fact[i+1]*i%mod;
    vector<vector<int64_t>> dp(n+1,vector<int64_t> (n*(n+1)+5));
    dp[1][n*(n+1)/2]=1;
    for (int k=2;k<=n;k++){
        for (int ij=-k+1;ij<=k-1;ij++){
            if (ij>0){
                for (int r=n*(n+1)-ij;r>=0;r--)
                    (dp[k][r+ij]+=(k-ij)*dp[k-1][r])%=mod;
            }
            else {
                for (int r=-ij;r<=n*(n+1);r++)
                    (dp[k][r+ij]+=(k+ij)*dp[k-1][r])%=mod;
            }
        }
    }
    // for (int i=1;i<=4;i++){
    //      for (int j=-5;j<=5;j++) cout<<dp[i][n*(n+1)/2+j]<<" ";
    //          cout<<'\n';
    // }
    int64_t finalsol=0;
    for (int k=0;k<n;k++){
        for (int ij=-1;ij>-(n-k);ij--){
            int64_t tmp=0;
            //cout<<i<<" "<<j<<"!\n";
            for (int r=n*(n+1)/2-ij+1;r<=n*(n+1)&&dp[n-k-1][r];r++) {
                (tmp+=dp[n-k-1][r]*fact[n-k+1]%mod*(n-k+ij)%mod)%=mod;
                //cout<<r-n*(n+1)/2<<" "<<dp[n-k-1][r]<<'\n';
            }
            finalsol=(finalsol+tmp)%mod;
        }
    }
    cout<<finalsol<<'\n';
}

#include <bits/stdc++.h>
using namespace std;

#define e1 first
#define e2 second
#define pb push_back
#define mp make_pair
#define boost {ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
#define eb emplace_back
#define OUT(x) {cout << x; exit(0); }
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define scanf(...) scanf(__VA_ARGS__)?:0
typedef long long int ll;
typedef unsigned long long ull;
typedef pair <int, int> PII;
typedef pair <ll, ll> PLL;
typedef pair <PLL, int> PLLI;
typedef pair <PII, PII> PP;
typedef pair <PII, int> PPI;
typedef pair <int, PII> PIP;
typedef pair <ll, int> PLI;
typedef unsigned int ui;
const int inf = 1e9+9;
const ll MOD = 1e9+696969;
#ifdef DEBUG
template<class T> int size(T &&x) {
	return int(x.size());
}
template<class A, class B> ostream& operator<<(ostream &out, const pair<A, B> &p) {
	return out << '(' << p.first << ", " << p.second << ')';
}
template<class T> auto operator<<(ostream &out, T &&x) -> decltype(x.begin(), out) {
	out << '{';
	for(auto it = x.begin(); it != x.end(); ++it)
		out << *it << (it == prev(x.end()) ? "" : ", ");
	return out << '}';
}
void dump() {}
template<class T, class... Args> void dump(T &&x, Args... args) {
	cerr << x << ";  ";
	dump(args...);
}
#endif
#ifdef DEBUG
  struct Nl{~Nl(){cerr << '\n';}};
# define debug(x...) cerr << (strcmp(#x, "") ? #x ":  " : ""), dump(x), Nl(), cerr << ""
#else
# define debug(...) 0 && cerr
#endif
mt19937_64 rng(time(0));
int random(int l, int r) {
	return uniform_int_distribution<int>(l, r)(rng);
}

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi;

#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using namespace atcoder;
using mint = modint;

int n, mod;
mint choose[510][510];
const int MAXINV = 50 * 49 + 1;
const int maxn = 52;
mint dp[maxn][maxn][MAXINV];
mint atmost[maxn][maxn][MAXINV];

mint base[maxn][MAXINV];

int main() {
	boost;
	cin >> n >> mod;
	mint::set_mod(mod);

	choose[0][0] = 1;
	FOR(i, 1, 500) {
		choose[i][0] = choose[i][i] = 1;
		for (int j = 1; j < i; ++j) choose[i][j] = choose[i-1][j] + choose[i-1][j-1];
	}

	base[1][0] = 1;
	for (int tot = 2; tot <= n; ++tot) {
		for (int inver = 0; inver <= tot * (tot - 1) / 2; ++inver) {
			for (int added_inversions = 0; added_inversions < tot; ++added_inversions) {
				if (inver >= added_inversions) base[tot][inver] += base[tot - 1][inver - added_inversions];
			}
		}
	}

	dp[1][1][0] = 1; //exactly one option
	for (int tot = 2; tot <= n; ++tot) {
		for (int pos_removed = 1; pos_removed <= tot; ++pos_removed) {
			for (int inver = 0; inver <= tot * (tot - 1) / 2; ++inver) {
				// this total, this elem removed, this number of inversions
				if (tot == pos_removed) {
					// we can take the base result - number of permutations with nothing removed and this many inversions
					dp[tot][pos_removed][inver] = base[tot - 1][inver];
				}
				else {
					// we are adding number "tot" to a previously valid result
					for (int added_inversions = 0; added_inversions < tot - 1; ++added_inversions) {
						if (inver >= added_inversions)
							dp[tot][pos_removed][inver] += dp[tot - 1][pos_removed][inver - added_inversions];
					}
				}
			}
		}
	}

	for (int tot = 0; tot <= n; ++tot) {
		for (int pos_removed = 0; pos_removed <= tot; ++pos_removed) {
			for (int inver = 0; inver <= tot * (tot - 1) / 2; ++inver) {
				atmost[tot][pos_removed][inver] = dp[tot][pos_removed][inver];
				if (inver > 0) atmost[tot][pos_removed][inver] += atmost[tot][pos_removed][inver - 1];
			}
		}
	}

	mint result = 0;
	for (int k = 0; k < n; ++k) {
		mint ways = choose[n][k];
		int remains = n - k;

		for (int p = 1; p <= remains; ++p) {
			for (int q = p + 1; q <= remains; ++q) {
				// we guarantee that p < q
				debug(ways.val(), remains, p, q);
				for (int inver = 0; inver <= remains * (remains - 1) / 2; ++inver) {
					// true_inver = inver + p - 1
					// true_inver2 = X + q - 1
					// inver + p - 1 > X + q - 1
					// inver + p > X + q
					// inver + p - q > X
					// X < inver + p - q
					mint incr = 0;
					if (inver + p - q - 1 >= 0) incr = ways * dp[remains][p][inver] * atmost[remains][q][inver + p - q - 1];
					result += incr;
					//debug(inver, incr.val(), dp[remains][p][inver].val(), atmost[remains][q][inver + p - q - 1].val(), inver + p - q - 1);
				}
			}
		}
	}

	cout << result.val();
}

// LUOGU_RID: 94385328
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls(x) ((x)<<1)
#define rs(x) ((x)<<1|1)
#define fi first
#define se second
#define mkp make_pair
#define PII pair<int,int>
const int N = 510, M = N * N; int mod;
int n, f[M], sf[M], g[M], sg[M], tmp[N];
void Add(int &x, int y) {
	x += y; if(x >= mod) x -= mod;
}
int main() {
	scanf("%d%d", &n, &mod);
	int lim = n * (n - 1) / 2;
	tmp[0] = 1; for(int i = 1; i < n; i++) tmp[i] = (ll)tmp[i - 1] * (n - i + 1) % mod;

	int ans = 0;
	g[0] = 1; for(int j = 0; j <= lim; j++) sg[j] = 1;
	f[0] = 1; for(int j = 0; j <= lim; j++) sf[j] = 1;
	for(int i = 0; i < n; i++) {
		if(i > 0) {
			for(int j = 0; j <= lim; j++) {
				if(j - (i - 1) - 1 >= 0) g[j] = (sg[j] + mod - sg[j - (i - 1) - 1]) % mod;
				else g[j] = sg[j];
			}
			for(int j = 0; j <= lim; j++) {
				sg[j] = g[j]; if(j > 0) Add(sg[j], sg[j - 1]);
			}
			for(int j = 0; j <= lim; j++) {
				for(int k = 0; k <= lim - j; k++)
					Add(f[j], (ll)g[k] * g[j + k] % mod);
				sf[j] = f[j]; if(j > 0) Add(sf[j], sf[j - 1]);
			}
		}
		//前n-i-1位p,q相同
		for(int a = 1; a <= i + 1; a++) {
			for(int b = a + 1; b <= i + 1; b++) {
				int ret = (sf[lim] + mod - sf[b - a]) % mod;
				Add(ans, (ll)tmp[n - i - 1] * ret % mod);
			}
		}
	}
	printf("%d\n", ans);
	return 0;
}
/*
不保证m为素数？
考虑前i位相同，第i+1位p比q小（枚举一下） tp-tq=j>=b-a+1 <= n-i-1 求f[n-i-1][(b-a+1)~sum]
那么我们要求f[i][j]，i个数，逆序对p比q多j
g[i][j] i个数逆序对为j
g[i][j]+=g[i-1][j-k] k\in[0,i-1]  前缀和一下还是可以n^3
f[i][j]=\sum (g[i][j+k]*g[i][k]) k为0~lim-j
还是能前缀和。
*/

#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<unordered_set>
#include<map>
#include<unordered_map>
#include<queue>
#include<cmath>
#include<deque>
#include<stack>
#include<iomanip>
#include<random>
#include<cstdio>
#include<string>
#include<cstring>
#include<fstream>
#include<numeric>
#include<bitset>
#include<cassert>

using namespace std;

const long long N = 51, M = 51 * 51;

long long n, m;
long long dp[N][N][M];
long long d[N][M];
long long p[N][N][M];

long long add(long long a, long long b) {
    return (a + b) % m;
}

long long mul(long long a, long long b) {
    return a * b % M;
}

void build() {
    dp[1][1][0] = 1;
    d[1][0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= i * (i - 1) / 2; j++) {
            for (int k = 1; k <= min(i, j + 1); k++) {
                dp[i][k][j] = d[i - 1][j - k + 1];
                p[i][k][j] = add(p[i][k][j - 1], dp[i][k][j]);
                d[i][j] = add(d[i][j], dp[i][k][j]);
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    //cout << fixed << setprecision(30);
    int _ = 1;
    //cin >> _;
    while (_--) {
        long long ans = 0;
        cin >>  n >> m;
        build();
        for (int i = 1; i <= n; i++) {
            for (int k = 1; k < i; k++) {
                for (int l = k + 1; l <= i; l++) {
                    for (int j = 1; j <= i * (i - 1) / 2 + k - 1; j++) {
                        ans = add(ans, mul(dp[i][k][j], p[i][l][j - 1]));
                    }
                }
            }
        }
        cout << ans << endl;
    }
}

#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <algorithm>
#include <deque>
#include <string>
#include <cmath>
#include <unordered_map>
using namespace std;

long long M;
int n;

map<int, long long> dp_lex[51], dp[51];
//dp_lex[i][j] = number of pairs (p,q) of permutations of length i such that
//p is lex. smaller than q, and p has exactly j more inversions than q.

long long work(){
    dp[1][0] = 1;
    for (int i=2;i<=n;i++){
        int mn, mx;
        mn = -(i-1)*(i-2)/2;
        mx = (i-1)*(i-2)/2;
        for (int j=0;j<n;j++){
            //put '1' j spaces apart in p and q.
            // 2 .. n gives a difference of k inversions
            for (int k=mn;k<=mx;k++){
                dp[i][k-j] += dp[i-1][k] * (i-j);
                dp[i][k-j] %= M;
                if (j != 0) {
                    dp[i][k+j] += dp[i-1][k] * (i-j);
                    dp[i][k+j] %= M;
                }

                if (k-j<= 0) continue;
                if (j > 0){
                    dp_lex[i][k-j] += dp[i-1][k] * (i-j);
                    dp_lex[i][k-j] %= M;
                }
                if (j == 0){
                    dp_lex[i][k] += dp_lex[i-1][k] * i;
                    dp_lex[i][k] %= M;

                }
            }
        }

    }
    long long ans = 0;
    for (int i=1;i<=n*(n-1)/2;i++){
        ans += dp_lex[n][i];
        if (ans >= M) ans -= M;
    }
    return ans%M;
}

int main(){
    cin >> n >> M;
    cout << work() << endl;

}

/*
Author: Zcus
Nlog: https://cnblogs.com/zcus
*/

#include <bits/stdc++.h>
using namespace std;

template<class T>
inline T read() {
	T s = 0, w = 1;
	char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') w = -1; c = getchar();}
	while (c >= '0' && c <= '9') { s = s * 10 + (c ^ 48); c = getchar();}
	return s * w;
}

#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ri read<int>
#define pii pair<int, int>
#define rl read<long long>
#define debug(x) cout << #x << " = " << x << endl
#define For(i, x, y) for (int ed = (y), i = (x); i <= ed; i++)
#define Rep(i, x, y) for (int ed = (y), i = (x); i >= ed; i--)
#define ddbug(x, y) cout << #x << " = " << x << " " << #y << " = " << y << "\n"
#define file(FILE_NAME) freopen(FILE_NAME".in", "r", stdin), freopen(FILE_NAME".out", "w", stdout)
#define filein(FILE_NAME) freopen(FILE_NAME".in", "r", stdin);
#define fileout(FILE_NAME) freopen(FILE_NAME".out", "w", stdout);

template<class T> inline bool Chkmax(T& x, const T& y) { return x < y ? x = y, true : false; }
template<class T> inline bool Chkmin(T& x, const T& y) { return x > y ? x = y, true : false; }

const int N = 251 * 501;
const int maxn = 1000;

int n, Mod, dp[2][maxn * maxn];
int A[maxn];

int res[maxn * maxn];
int main() {
	n = ri(), Mod = ri();
	A[0] = 1;
	for (int i = 1; i <= n; i++) A[i] = 1ll * A[i - 1] * (n - i + 1) % Mod;
	int ans = 0;
	dp[0][N] = 1;
	for (int i = 1; i < n; i++) {
		memset(dp[i & 1], 0, sizeof dp[i & 1]);
		int now = i & 1;
		int C = (i + 1) * (i + 1) / 2;
		for (int j = N - C; j <= N + C; j++) {
			int w = dp[now ^ 1][j];
			(dp[now][j + i + 1] += w) %= Mod;
			if (j - i + 1 >= 0) (dp[now][j - i + 1] += w) %= Mod;
			(dp[now][j + 1] += 1ll * (Mod - 2) * w % Mod) %= Mod;
		}
		for (int zzm = 1; zzm <= 2; zzm++) {
			for (int j = N + C; j >= N - C; j--) {
				(dp[now][j] += dp[now][j + 1]) %= Mod;
			}
			for (int j = N - C; j <= N + C; j++)
				dp[now][j] = dp[now][j + 1];
		}
		res[C + 1] = 0;
		for (int j = C; j >= 0; j--) res[j] = res[j + 1] + dp[now][N + j];
		for (int a = 0; a <= i; a++) {
			for (int b = a + 1; b <= i; b++) {
				(ans += 1ll * A[n - i - 1] * res[b - a + 1] % Mod) %= Mod;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define x first
#define y second
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x,T y){x<y?x=y:T();}
template <typename T> void chkmin(T &x,T y){y<x?x=y:T();}
template <typename T> void readint(T &x)
{
	x=0;int f=1;char c;
	for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())x=x*10+(c-'0');
	x*=f;
}
int MOD;
inline int dmy(int x){return x>=MOD?x-MOD:x;}
inline void inc(int &x,int y){x=dmy(x+y);}
int qmi(int x,int y)
{
	int ans=1;
	for(;y;y>>=1,x=1ll*x*x%MOD)
		if(y&1)ans=1ll*ans*x%MOD;
	return ans;
}
const int MAXN=55;

int n,fac[MAXN],g[MAXN][MAXN*MAXN],f[MAXN][MAXN],suf[MAXN*MAXN];

int main()
{
	#ifdef LOCAL
	freopen("code.in","r",stdin);
//	freopen("code.out","w",stdout);
	#endif
	readint(n),readint(MOD);
	fac[n+1]=1;
	for(int i=n;i;--i)fac[i]=1ll*fac[i+1]*i%MOD;
	g[n+1][0]=1;
	for(int i=n,s=0;i;--i)
	{
		for(int k=0;k<=s;++k)
			for(int j=0;j<=n-i;++j)
				inc(g[i][k+j],g[i+1][k]);
		s+=n-i;
		suf[s+1]=0;
		for(int k=s;k>=0;--k)suf[k]=dmy(suf[k+1]+g[i][k]);
		for(int u=1;u<=n;++u)
			for(int k=0;k<=s;++k)
				inc(f[i][u],1ll*g[i][k]*suf[k+u+1]%MOD);
	}
	int res=0;
	for(int i=1;i<=n;++i)
		for(int x=0;x<=n-i;++x)
			for(int y=x+1;y<=n-i;++y)
				inc(res,1ll*fac[n-i+2]*fac[n-i+2]%MOD*f[i+1][y-x]%MOD);
	printf("%d\n",res);
	return 0;
}

#include <bits/stdc++.h>

#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort((x).begin(), (x).end()); (x).erase(unique((x).begin(), (x).end()), (x).end())
#define imie(x) #x << ": " << x

using namespace std;

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

template <typename T, typename U>
istream& operator >>(istream& istr, pair<T, U>& pr) {
	return istr >> pr.first >> pr.second;
}

template <typename T = int>
T nxt(istream& istr = cin) {
	T x;
	istr >> x;
	return x;
}

template <typename T>
struct TypeModular {
	using Type = typename decay<decltype(T::value)>::type;
	Type val;

	static constexpr Type mod() {
		return T::value;
	}

	TypeModular(long long _val = 0) {
		if (_val < 0 || (_val > 0 && _val >= mod())) {
			val = _val % mod();
			if (val < 0) {
				val += mod();
			}
		} else {
			val = _val;
		}
	}

	friend TypeModular operator -(const TypeModular& a) {
		return {-a.val};
	}

	friend TypeModular operator +(const TypeModular& a, const TypeModular& b) {
		Type res = a.val + b.val;
		if (res >= mod()) {
			res -= mod();
		}
		return {res};
	}

	friend TypeModular operator -(const TypeModular& a, const TypeModular& b) {
		Type res = a.val - b.val;
		if (res < 0) {
			res += mod();
		}
		return {res};
	}

	friend TypeModular operator *(const TypeModular& a, const TypeModular& b) {
		return {1ll * a.val * b.val};
	}

	friend TypeModular operator /(const TypeModular& a, const TypeModular& b) {
		return a * b.inv();
	}

	TypeModular& operator +=(const TypeModular& b) {
		val += b.val;
		if (val >= mod()) {
			val -= mod();
		}
		return *this;
	}

	TypeModular& operator -=(const TypeModular& b) {
		val -= b.val;
		if (val < 0) {
			val += mod();
		}
		return *this;
	}

	TypeModular& operator *=(const TypeModular& b) {
		val = 1ll * val * b.val % mod();
		return *this;
	}

	TypeModular& operator /=(const TypeModular& b) {
		*this *= b.inv();
		return *this;
	}

	TypeModular& operator ++() {
		val += 1;
		if (val == mod()) {
			val = 0;
		}
		return *this;
	}

	TypeModular operator ++(int) {
		TypeModular tmp(*this);
		operator ++();
		return tmp;
	}

	friend bool operator ==(const TypeModular& a, const TypeModular& b) {
		return a.val == b.val;
	}

	friend bool operator !=(const TypeModular& a, const TypeModular& b) {
		return a.val != b.val;
	}

	TypeModular pow(long long b) const {
		TypeModular res{1}, a{*this};
		while (b) {
			if (b & 1ll) {
				res *= a;
			}
			b >>= 1;
			a *= a;
		}
		return res;
	}

	TypeModular inv() const {
		assert(val);
		return _inv(val, mod());
	}

	int _inv(int a, int b) const {
		return a == 1 ? a : b - 1ll * _inv(b % a, a) * b / a % b;
	}

	explicit operator Type() const {
		return val;
	}

	explicit operator bool() const {
		return val;
	}
};

template <typename T = int>
struct integral_variable {
	static T value;
};

template <typename T> T integral_variable<T>::value;

void set_prime(int p) {
	integral_variable<int>::value = p;
}

template <typename T>
ostream& operator <<(ostream& ostr, const TypeModular<T>& x) {
	return ostr << x.val;
}

template <typename T>
istream& operator >>(istream& istr, TypeModular<T>& x) {
	x = nxt(istr);
	return istr;
}

template <int mod>
using Modular = TypeModular<integral_constant<int, mod>>;
#define all(x) (x).begin(), (x).end()
#define itn int
#define make_unique(x) sort((x).begin(), (x).end()); (x).erase(unique((x).begin(), (x).end()), (x).end())

inline int nxt() {
	int x;
	cin >> x;
	return x;
}

using Mint = TypeModular<integral_variable<int>>;

const int N = 505;
const int M = N * N / 2;
Mint with_inv[N][M];
Mint tmp[M];
Mint huemp[M];

Mint C[N][N];

void solve() {
	int nn = nxt(), mod = nxt();
	set_prime(mod);

	with_inv[0][0] = 1;
	for (int n = 1; n < N; ++n) {
		Mint cur = 0;
		for (int i = 0; i <= n * (n - 1) / 2; ++i) {
			cur += with_inv[n - 1][i];
			if (i >= n) {
				cur -= with_inv[n - 1][i - n];
			}
			with_inv[n][i] = cur;
		}
	}
	for (int i = 0; i < N; ++i) {
		C[i][0] = C[i][i] = 1;
		for (int j = 1; j < i; ++j) {
			C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
		}
	}

	Mint ans = 0;
	for (int n = 2; n < nn; ++n) {
		Mint cur = 0;
		partial_sum(with_inv[n], with_inv[n] + n * (n - 1) / 2 + 1, tmp);
		for (int d = 1; d <= n; ++d) {
			for (int i = d + 1; i <= n * (n - 1) / 2; ++i) {
				cur += with_inv[n][i] * tmp[i - d - 1] * (n + 1 - d);
			}
		}
		ans += cur * C[nn][n + 1];
	}
	cout << ans << "\n";
}

int main() {
	int t = 1; // nxt();
	while (t--) {
		solve();
	}

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int M;

int add(int a, int b) {
  a += b;
  if (a >= M) return a - M;
  if (a < 0) return a + M;
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

void addup(int &a, int b) {
  a = add(a, b);
}

const int N = 50 + 7;
int n, cnt[N][N * N], sum[N][N * N], sol[N];

void csum(int i) {
  sum[i][0] = cnt[i][0];
  for (int j = 1; j < N * N; j++) {
    sum[i][j] = add(sum[i][j - 1], cnt[i][j]);
  }
}

int getsum(int i, int l, int r) {
  return sum[i][r] - (l ? sum[i][l - 1] : 0);
}

int main() {
  ///freopen ("input", "r", stdin);
  cin >> n >> M;

  cnt[0][0] = 1 % M;
  csum(0);
  for (int i = 1; i < N; i++) {
    for (int j = 0; j < N; j++) {
      int l = max(0, j - (i - 1)), r = j;
      cnt[i][j] = getsum(i - 1, l, r);
    }
    assert(cnt[i][N * N - 1] == mul(i, cnt[i - 1][N * N - 1]));
    csum(i);
  }

  /// ff < ss => ans[i] = i * ans[i - 1] + sol[i]

  for (int l = 1; l <= n; l++) {
    for (int x = 1; x <= l; x++) {
      for (int y = x + 1; y <= l; y++) {
        int init = sol[l];
        /**

        totalx = ix + x - 1
        totaly = iy + y - 1
        ix + x - 1 > iy + y - 1
        ix + x - y > iy
        ix + x - y - 1 >= iy

        **/
        for (int ix = 0; ix <= l * l; ix++) {
          if (!cnt[l][ix]) continue;
          int last = ix + x - y - 1;
          if (last >= 0) {
            addup(sol[l], mul(cnt[l - 1][ix], sum[l - 1][last]));
          }
        }
      }
    }
  }

  for (int i = 1; i <= n; i++) {
   /// cout << i << " : " << sol[i] << "\n";
  }

  int print = 0;
  for (int i = 1; i <= n; i++) {
    print = add(sol[i], mul(i, print));
  }
  cout << print << "\n";
  return 0;
}

#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define per(i,a,b) for(ll i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const int MAXN=510,MAXM=510*510,ADD=501*501/2+1;
int n,mod;
int f[2][MAXM],sum[2][MAXM],fact[MAXN],c[MAXN][MAXN],g[MAXN],ans[MAXN];
int s[MAXM];
int main(){
	cin>>n>>mod;
	fact[0]=1;
	rep(i,1,n){
		fact[i]=fact[i-1]*i%mod;
	}
	c[0][0]=1;
	rep(i,1,n){
		c[i][0]=1;
		rep(j,1,i)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
	}
	//f[i][j]是长度为i的排列对，逆序对差为j的数量
	f[1&1][0+ADD]=1;rep(j,0,n*(n-1)/2)sum[1&1][j+ADD]=1;
	rep(i,2,n){
		memset(sum[i&1],0,sizeof sum[i&1]);
		rep(k,0,i-1){
			f[i&1][-i*(i-1)/2+ADD]=((ll)f[i&1][-i*(i-1)/2+ADD]+(i-k)*f[(i-1)&1][-i*(i-1)/2+k+ADD])%mod;
		}
		rep(j,-(i*(i-1)/2)+1,i*(i-1)/2){
			f[i&1][j+ADD]=((ll)f[i&1][j-1+ADD]+sum[(i-1)&1][Min(j+i-1,n*(n-1)/2)+ADD]-sum[(i-1)&1][j-1+ADD]-
			sum[(i-1)&1][j-1+ADD]+sum[(i-1)&1][Max(j-i-1,-n*(n-1)/2)+ADD])%mod;
		}
		rep(j,-n*(n-1)/2,n*(n-1)/2)sum[i&1][j+ADD]=(sum[i&1][j-1+ADD]+f[i&1][j+ADD])%mod;
		memset(s,0,sizeof s);
		s[i*(i-1)/2+ADD]=f[i&1][i*(i-1)/2+ADD];
		per(j,i*(i-1)/2-1,-n*(n-1)/2){
			s[j+ADD]=(s[j+1+ADD]+f[i&1][j+ADD])%mod;
		}
		rep(x,1,i+1){
			rep(y,x+1,i+1){
				//分别为x,y方案数
				ll diff=y-x;
				g[i+1]=(g[i+1]+s[diff+1+ADD])%mod;
			}
		}
	}
	rep(i,2,n){
		ans[i]=((ll)ans[i-1]*i+g[i])%mod;
	}
	printf("%lld",ans[n]);
	return 0;
}

#include<bits/stdc++.h>
#define I inline
#define RI register int
#define rep(i,a,b) for(RI i=a;i<=b;++i)
#define dow(i,a,b) for(RI i=a;i>=b;--i)
using namespace std;
const int N=4e5+5;
long long T,n,mo,a[N],sum[N],b[N],c[N];
int main(){
	scanf("%lld%lld",&n,&mo);n-=3;RI now=3,res=0;
	if(n<=0) return printf("0"),0;
	a[0]=1,a[1]=2,a[2]=2,a[3]=1;
	rep(i,1,n){
		now=now+i+2;res=res*(i+3)%mo;
		rep(j,0,i+2){
			rep(k,j+1,i+2){
				rep(l,0,now) c[l]=b[l]=0;
				rep(l,j,now) c[l]=a[l-j];
				rep(l,k,now) b[l]=a[l-k];
				sum[0]=b[0];rep(l,1,now) sum[l]=(sum[l-1]+b[l])%mo;
				rep(l,1,now) res+=c[l]*sum[l-1]%mo,res%=mo;
			}
		}
		rep(j,0,now) b[j]=0;
		rep(j,0,now)
			rep(k,0,i+2)
				b[j+k]=b[j+k]+a[j]>=mo?b[j+k]+a[j]-mo:b[j+k]+a[j];
	}
	return printf("%d\n",res),0;
}

#include <iostream>
#include <random>
#include <chrono>
#include <ctime>
#include <string>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
using ll = long long;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int N = 101;
int n, mod;
int f[N][N * N];
int pp[N][N * N];
int add(int x, int y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
}
int mult(int x, int y) {
    return 1ll * x * y % mod;
}
int A(int n, int m) {
    if (n < m) return 0;
    int ret = 1;
    for (int i = 1; i <= m; i++)
        ret = mult(ret, n - m + i);
    return ret;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int ans = 0;
    cin >> n >> mod;
    int R = n * (n - 1) / 2 + 10;
    f[0][0] = 1;
    for (int i = 0; i < n; i++)
        for (int inv = 0; inv <= i * (i - 1) / 2; inv++)
            for (int plus = 0; plus <= i; plus++)
                f[i + 1][inv + plus] = add(f[i + 1][inv + plus], f[i][inv]);
    for (int i = 0; i <= n; i++) {
        pp[i][0] = f[i][0];
        for (int j = 1; j < R; j++)
            pp[i][j] = add(pp[i][j - 1], f[i][j]);
    }
    for (int pref = 0; pref <= n - 2; pref++) {
        int koef = A(n - 2, pref);
        int cur = 0;
        for (int x = 1; x <= n - pref; x++)
            for (int y = x + 1; y <= n - pref; y++) {
                for (int cnt1 = 0; cnt1 < R; cnt1++) {
                    int cnt2 = cnt1 + x - y;
                    if (cnt2 > 0)
                        cur = add(cur, mult(f[n - pref - 1][cnt1], pp[n - pref - 1][cnt2 - 1]));
                    //for (int cnt2 = 0; cnt2 < cnt1 + x - y; cnt2++)
                      //  cur = add(cur, mult(f[n - pref - 1][cnt1], f[n - pref - 1][cnt2]));
                }
            }
        ans = add(ans, mult(cur, koef));
    }
    cout << ans;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define fastio() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define test() int t;cin>>t;for(int test=1;test<=t;test++)
#define pb push_back
#define nl cout<<"\n"
#define F first
#define S second
#define all(x) x.begin(),x.end()

template<class C> void min_self( C &a, C b ){ a = min(a,b); }
template<class C> void max_self( C &a, C b ){ a = max(a,b); }

ll MOD = 1000000007;
ll mod( ll n, ll m=MOD ){ n%=m;if(n<0)n+=m;return n; }

const int MAXN = 55;
const ll MAXINV = 1485;
const int LOGN = 21;
const ll INF = 1e14;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};

template<class T1, class T2> void add( T1 &x, T2 y, ll m = MOD )
{
    x += y;
    if( x >= m )
        x -= m;
}

template<class T1, class T2> void sub( T1 &x, T2 y, ll m = MOD )
{
    x -= y;
    if( x < 0 )
        x += m;
}

ll dp[MAXN][MAXINV];
ll pref[MAXN][MAXINV];

ll get(int i, int l, int r)
{
    ll ans = pref[i][r];
    if(l>0)
        sub(ans, pref[i][l-1]);
    return ans;
}

ll ncr[MAXN][MAXN];
ll fact[MAXN];
void init()
{
    fact[0] = 1;
    for(int i=0; i<MAXN; i++)
    {
        for(int j=0; j<=i; j++)
        {
            if(j==0 || j==i)
                ncr[i][j] = 1;
            else
            {
                ncr[i][j] = ncr[i][j-1];
                add(ncr[i][j], ncr[i-1][j-1]);
            }
        }
        if(i)
            fact[i] = mod(fact[i-1]*i);
    }
}

int main()
{
    fastio();
    #ifdef rushabh
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif

    ll n; cin>>n>>MOD;
    ll ninv = (n*(n-1))/2;
    init();

    dp[0][0] = 1;
    for(int i=0; i<=ninv; i++)
        pref[0][i] = 1;

    for(int len=1; len<=n; len++)
    {
        for(int inv=0; inv<=ninv; inv++)
        {
            add(dp[len][inv], get(len-1, inv-len+1, inv));
            // cout<<len<<" "<<inv<<" "<<dp[len][inv],nl;
        }

        pref[len][0] = dp[len][0];
        for(int inv=1; inv<=ninv; inv++)
        {
            pref[len][inv] = pref[len][inv-1];
            add(pref[len][inv], dp[len][inv]);
        }
    }

    ll ans = 0;
    for(int len=0; len<n; len++)
    {
        ll tans = 0;
        for(int p=1; p<=n-len; p++)
        {
            for(int q=p+1; q<=n-len; q++)
            {
                int diff = q-p;
                ll ttans = 0;
                for(int inv=diff+1; inv<=ninv; inv++)
                {
                    // cout<<get(n-len-1, 0, inv-diff-1),nl;
                    add(ttans, mod(get(n-len-1, 0, inv-diff-1)*dp[n-len-1][inv]));
                }
                // cout<<p<<" "<<q<<" "<<ttans,nl;
                add(tans, ttans);
            }
        }
        tans = mod(tans * ncr[n][len]);
        tans = mod(tans * fact[len]);
        add(ans, tans);
        // cout<<len<<" "<<tans,nl;
    }

    cout<<ans,nl;

    cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    return 0;
}

#include <iostream>
#include <cstring>
#include <cstdio>
#define N 505
#define ll long long
using namespace std;
ll f[N][N*N/2],s[N*N/2];
int main()
{
	int i,j,k,n;
	ll mod,ans=0;
	scanf("%d %lld",&n,&mod);
	f[0][0]=1;
	for(i=1;i<=n;++i)
		for(j=0;j<=i*(i-1)/2;++j)
			for(k=0;k<=min(i-1,j);++k)
				(f[i][j]+=f[i-1][j-k])%=mod;
	for(i=1;i<n;++i)
	{
		s[0]=f[i][0];
		for(j=1;j<=i*(i-1)/2;++j)
			s[j]=(s[j-1]+f[i][j])%mod;
		for(k=1;k<=i;++k)
			for(j=0;j+k<i*(i-1)/2;++j)
				(ans+=(s[i*(i-1)/2]-s[j+k])*f[i][j]%mod*(i+1-k)%mod)%=mod;
	}
	printf("%lld\n",(ans+mod)%mod);
	return 0;
}

// ¯\_(ツ)_/¯
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;

#define all(x)                      (x).begin(),(x).end()
#define X                           first
#define Y                           second
#define sep                         ' '
#define endl                        '\n'
#define debug(x)                    cerr << #x << ": " <<  x << endl;

const ll MAXN = 1e6 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7; // 998244353; // 1e9 + 9;

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	return 0;
}

#include<bits/stdc++.h>

using namespace std;
//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#define rep(i, x, y) for(int i = x; i <= y; ++i)
#define repi(i,x,y) for(int i = x; i >= y; --i)
#define ci(x) int x; cin>> x
#define TC(t) ci(t); while(t--)
#define fi first
#define se second
#define pb push_back
#define all(x) x.begin(), x.end()
#define cii(x, y) ci(x); ci(y)
#define ciii(x, y, z) ci(x); ci(y); ci(z)
#define mp make_pair
//#define int long long
typedef long long ll;
typedef vector<int> vi;
const int N = 100 + 5;
const int NN = 16 + 15;
const int mod = 998244353;
const int mod1 = 1e9 + 9;
const int pi = 31;
const int inf = 1e9 + 6;
const int block = 500;
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};

void readfile(){
    #ifdef ONLINE_JUDGE
    #else
        freopen("text.inp", "r", stdin);
    #endif // ONLINE_JUDGE
//    freopen("barnpainting.in", "r", stdin);
//    freopen("barnpainting.out", "w", stdout);
}

int n, m;

void inp(){
    cin >> n >> m;
}

int add(int x, int y){
    x += y;
    while(x < 0) x += m;
    while(x >= m) x -= m;
    return x;
}

int mul(int x, int y){
    x = (x * 1LL * y) % m;
    while(x < 0) x += m;
    while(x >= m) x -= m;
    return x;
}

int bipow(int a, int n){
    if(n==0) return 1;
    int temp = bipow(a, n>>1);
    int temp1 = mul(temp, temp);
    if(n&1) return mul(temp1, a);
    return temp1;
}

int C[55][55]; // nCk
int f[55][55][2505], s[55][55][2505];
int p[55];

void prep(){
    C[0][0] = 1;
    rep(i,1,n)
        rep(j,0,i){
            if(j==0 || j==i) C[i][j] = 1;
            else C[i][j] = add(C[i-1][j], C[i-1][j-1]);
        }
    f[1][1][0] = 1;
    rep(i,2,n){
        rep(j,1,i){
            int a = j - 1;
            rep(u,0,i*(i-1)/2){
                if(u-a >= 0)
                    rep(v,1,i-1)
                        f[i][j][u] = add(f[i][j][u], f[i-1][v][u-a]);
                s[i][j][u] = add(s[i][j][u-1], f[i][j][u]);
            }
        }
    }
    p[0] = 1;
    rep(i,1,n) p[i] = mul(p[i-1], i);
}

int g[55][55][55];

void process(){
    prep();
    int res = 0;
    rep(i,1,n){
        rep(j,1,n)
            rep(k,1,n)
                rep(temp,1,i*(i-1)/2)
                    g[i][j][k] = add(g[i][j][k], mul(f[i][j][temp], s[i][k][temp-1]));
    }
    rep(pos,1,n){
        rep(val1, 1, n-1)
            rep(val2, val1 + 1, n){
                int num_smaller = val1 - 1;
                rep(r, 0, num_smaller){
                    int l = num_smaller - r;
                    int r1 = val2 - 1 - l;
                    if(l > pos - 1) continue;
                    if(r > n - pos || r1 > n - pos) continue;
                    int dem_l = mul(C[pos-1][l], p[pos - 1]);
                    int temp = g[n-pos+1][r+1][r1+1];
                    temp = mul(temp, dem_l);
                    res = add(res, temp);
                }
            }
    }
    cout << res;
}

int main() {
    readfile();
    ios_base::sync_with_stdio(0);
    cin.tie(0);
//    TC(t){
        inp();
        process();
//        reset();
//    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define M 500000
typedef long long ll;
typedef unsigned long long ull;
inline ll read() {
    char ch;
    ll f = 1, res = 0;
    while ((ch = getchar()) < '0' || ch > '9')
        if (ch == '-') f = -1;
    while (ch >= '0' && ch <= '9') {
        res = (res << 1) + (res << 3) + (ch ^ 48);
        ch = getchar();
    }
    return f * res;
}
inline void pt(ll u,ll mod) {
    printf("%lld", u);
    if (mod == 1)
        putchar(' ');
    else if (mod == 2)
        putchar('\n');
}

ll dp[51][2510];
ll sum[51][2510];
ll s[51];
ll mul[51];

int main() {
    //freopen("../in", "r", stdin);
    //freopen("../out", "w", stdout);
    ll n = read(), mod = read();
    mul[0] = 1;
    for (ll i = 1; i <= n; i++)
        mul[i] = mul[i-1] * (n+i-1) % mod;

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

    for (ll i = 2; i <= n; i++) {
        for (ll j = 0; j <= i * (i - 1) / 2; j++) {
            for (ll k = 0; k < i && j >= k; k++) {
                if (j - k <= i - 1)
                    dp[i][j] += dp[i - 1][k];
                dp[i][j] %= mod;
            }

            sum[i][j] = dp[i][j];
            if (j)
                sum[i][j] += dp[i][j - 1];
        }

        for (ll j = 1; j <= n; j++)
            for (ll k = j + 1; k <= n; k++)

                for (ll w = 0; w < i * i; w++) {
                    s[i] += (w + j - k - 1 >= 0) ? sum[i - 1][w + j - k - 1] * dp[i - 1][w] : 0;
                    s[i] %= mod;
//                    cout<<s[i]<<endl;
                }

    }
    ll ans = 0;

    for (ll i = 1; i <= n; i++) {

//        cout<<s[i]<<':'<<mul[n - i]<<endl;
        ans += s[i] * mul[n - i] % mod;
        ans %= mod;
    }

    pt(ans, 2);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,l,r) for(ll i = (l); i < r; i++)
#define Rep(i,l,r,v) for(ll i = (l); i < r; i+=v)
#define per(i,r,l) for(int i = (r); i >= l; i--)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
#define pb push_back
#define ff first
#define ss second

const ll maxn = 55, inf = 1e9 + 5;
ll mod;
ll f[maxn][maxn], c[maxn][maxn], fc[maxn];
int n;

void init(){
    fc[0] = 1;
    rep(i,1,n + 1) fc[i] = fc[i-1]*i%mod;
    c[0][0] = 1;
    rep(i,1,n + 1){
        c[i][0] = 1;
        rep(j,1,n + 1){
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1])%mod;
        }
    }
}

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> mod;
    init();
    f[1][0] = 1;
    rep(i,2,n + 1){
        rep(d,0,i + 1){
            rep(j,1,i + 1){
                rep(k,1,i + 1){
                    f[i][d] += f[i - 1][abs(d - (j - k))];
                }
            }
        }
    }
    ll ans = 0;
    rep(i,0,n-1){
        ll x = 0;
        int d = n - i;
        rep(j,1,d + 1){
            rep(i,1,j){
                rep(k,j - i + 1, n + 1){
                    x += f[d - 1][k];
                    x %= mod;
                }
            }
        }
        ans += 1LL*c[n][i]*fc[i]%mod*x%mod;
        ans %= mod;
    }
    cout << ans;
    return 0;
}