//#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse2")

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

int solve(int64_t n, int64_t m) {
  int64_t ans = 0;
  vector<vector<vector<int64_t>>> DP(3*n+1, vector<vector<int64_t>>(n+1, vector<int64_t>(n+1)));
  auto dp = [&](int64_t a, int64_t b, int64_t c) -> int64_t {
              if (a<0 || b<0 || c<0) return 0;
              return DP[a][b][c];
            };
  for (int64_t b1 = 0; b1 <= 3*n; ++b1) {
    for (int64_t b2 = 0; b2 <= n; ++b2) {
      for (int64_t b3 = 0; b3 <= n; ++b3) {
        if (b1 == 0 && b2 == 0 && b3 == 0) {
          DP[0][0][0] = 1;
          continue;
        }
        int64_t num_els = b1 + 2*b2 + 3*b3;
        if (num_els > 3*n)
          break;
        DP[b1][b2][b3] = (dp(b1-1, b2, b3) +
                          dp(b1, b2-1, b3)*(num_els-1) +
                          dp(b1, b2, b3-1)*(num_els-2)*(num_els-1))%m;
        if (num_els == 3*n && b2+b3 <= n &&
            b1 == 3*(n - b3 - b2) + b2) {
          ans += DP[b1][b2][b3];
        }
      }
    }
  }

  return ans%m;
}

int solve_v2(int n, int m) {
  int ans = 0;
  vector<vector<vector<int32_t>>> DP(4, vector<vector<int32_t>>(n+1, vector<int32_t>(n+1)));
  auto dp_at = [&](int num_els, int b23, int b3) -> int32_t& {
                 return DP[num_els%4][b23][b3];
               };
  auto dp = [&](int num_els, int b23, int b3) -> int {
              if (num_els<0 || b23<0 || b3 < 0 || b3>b23) return 0;
              return DP[num_els%4][b23][b3];
            };
  dp_at(0, 0, 0) = 1;
  
  for (int num_els = 1; num_els <= 3*n; ++num_els) {
    if (num_els%1000==0)
      cout << "num_els="<<num_els << endl;
    for (int b23 = 0; b23 <= n; ++b23) {
      for (int b3 = 0; b3 <= b23 && 2*b23 + b3 <= num_els; ++b3) {
        dp_at(num_els, b23, b3) = (dp(num_els-1, b23, b3) +
                                   (int64_t)dp(num_els-2, b23-1, b3)*(num_els-1) +
                                   (int64_t)dp(num_els-3, b23-1, b3-1)*(num_els-1)*(num_els-2))%m;
      }
    }
  }
  for (int b2 = 0; b2 <= n; ++b2)
    for (int b3 = 0; b2 + b3 <= n && 2*b2 + 3*b3 <= 3*n; ++b3) {
      ans += dp(3*n, b2 + b3, b3);
      ans %= m;
    }
  return ans%m;
}

vector<vector<int>> CC;

int nCr(int n, int r) {
  return CC[n][r];
}

void init_nCr(int N, int m) {
  CC = vector<vector<int>>(N+1, vector<int>(N+1));
  CC[0][0] = 1;
  for (int n = 1; n <= N; ++n) {
    for (int k = 0; k <= n; ++k) {
      if (k==0 || k==n)
        CC[n][k] = 1;
      else
        CC[n][k] = (CC[n-1][k-1] + CC[n-1][k])%m;
    }
  }
}

int solve_v3(int n, int m) {
  int ans = 0;
  vector<vector<int32_t>> DP(n+1, vector<int32_t>(n+1));
  auto dp_at = [&](int b23, int b3) -> int32_t& {
                 return DP[b23][b3];
               };
  auto dp = [&](int b23, int b3) -> int {
              if (b23<0 || b3 < 0 || b3>b23) return 0;
              return DP[b23][b3];
            };
  
  for (int b23 = 0; b23 <= n; ++b23) {
    for (int b3 = 0; b3 <= b23 && 2*b23 + b3 <= 3*n; ++b3) {
      if (b23 == 0 && b3 == 0) {
        dp_at(0, 0) = 1;
        continue;
      }
      int num_els = 2*b23 + b3;
      dp_at(b23, b3) = ((int64_t)dp(b23-1, b3)*(num_els-1) +
                        (int64_t)dp(b23-1, b3-1)*(num_els-1)*(num_els-2))%m;
    }
  }
  for (int b23 = 0; b23 <= n; ++b23)
    for (int b3 = 0; b3 <= b23; ++b3) {
      int b1 = 3*n - (2*b23 + b3);
      ans += dp(b23, b3)*nCr(3*n, b1);
      ans %= m;
    }
  return ans%m;
}


signed main() {
  ios_base::sync_with_stdio(false), cin.tie(nullptr);
  
  int n, m; cin >> n >> m;
  init_nCr(3*n, m);
  //if (n < 315) {
  //  cout << solve(n, m) << '\n';
  //  cout << flush;
  //}
  //cout << solve_v2(n, m) << '\n';
  cout << solve_v3(n, m) << '\n';  
}


Measured memory_bytes: 297472