Problem p03989 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i++)
#define reps(i, x, n) for (int i = x; i < (n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
#define all(X) (X).begin(), (X).end()
#define X first
#define Y second
#define pb push_back
#define eb emplace_back

using namespace std;
typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

template <class A, size_t N, class T> void Fill(A (&a)[N], const T &v) {
  fill((T *)a, (T *)(a + N), v);
}

const ll INF = 1e9 + 7;
const ll MOD = 924844033;

// n^m%MOD を求める。O( log(m) )
ll modpow(ll n, int m) {
  ll ret = 1;
  for (int i = 1; i <= m; i <<= 1, (n *= n) %= MOD) {
    if (m & i)
      (ret *= n) %= MOD;
  }
  return ret;
}

// 逆元を求める
ll modinv(ll n) { return modpow(n, MOD - 2); }

// 階乗を求める。O(1)  準備O( n*log(n) )
// fact[n]     : nの階乗
// fact.inv[n] : nの階乗の逆元
class FACTORIAL {
public:
  vector<ll> fact, inv;
  FACTORIAL(int MAX_NUM) : fact(MAX_NUM), inv(MAX_NUM) {
    fact[0] = inv[0] = 1;
    for (ll i = 1; i < MAX_NUM; i++) {
      fact[i] = (fact[i - 1] * i) % MOD;
      inv[i] = modinv(fact[i]);
    }
  }
  const ll &operator[](const int i) const { return fact[i]; }
} fact(1000006); // nの最大値を指定

// 組み合わせ(Combinationを求める) O(1)
ll cmb(unsigned int n, unsigned int r) {
  if (n < r)
    return 0;
  return fact[n] * fact.inv[r] % MOD * fact.inv[n - r] % MOD;
}

ll dp[4005][4005] = {};
ll dp2[4005][4005] = {};
int main() {
  // ios_base::sync_with_stdio(false);
  ll N, K, ans = 0;

  cin >> N >> K;

  dp[0][0] = 1;
  rep(i, 2 * N) rep(j, 2 * N) {
    dp[i][j] %= MOD;
    dp[i + 2][j + 1] += dp[i][j];
    dp[i + 1][j + 0] += dp[i][j];
  }
  // rep(i,2*N){
  // 	rep(j,2*N) cout << dp[i][j] << " ";
  // 	cout << endl;
  // }

  dp2[0][0] = 1;
  rep(i, 2 * K) {
    rep(j, 2 * N) dp2[i + 1][j] += dp2[i][j];
    rep(j, N) {
      // int m = (N - 1 - i) / K;
      int m = (N - 1 - i) / K;
      if (i >= K)
        m = (N - 1 - i + K) / K;
      reps(k, 1, m + 1) {
        dp2[i + 1][j + k] += dp2[i][j] * dp[m + 1][k];
        dp2[i + 1][j + k] %= MOD;
      }
    }
  }
  // rep(i,N+N) cout << dp2[2*K][i] << ", ";
  // cout << endl;

  rep(i, N + N) {
    ans += MOD;
    ans += dp2[2 * K][i] * (i % 2 ? -1 : +1) * fact[N - i];
    ans %= MOD;
    // cout << i << " : " << dp2[2*K][i] * (i%2 ? -1 : +1) * fact[N - i] <<
    // endl;
  }

  cout << ans << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i++)
#define reps(i, x, n) for (int i = x; i < (n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
#define all(X) (X).begin(), (X).end()
#define X first
#define Y second
#define pb push_back
#define eb emplace_back

using namespace std;
typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

template <class A, size_t N, class T> void Fill(A (&a)[N], const T &v) {
  fill((T *)a, (T *)(a + N), v);
}

const ll INF = 1e9 + 7;
const ll MOD = 924844033;

// n^m%MOD を求める。O( log(m) )
ll modpow(ll n, int m) {
  ll ret = 1;
  for (int i = 1; i <= m; i <<= 1, (n *= n) %= MOD) {
    if (m & i)
      (ret *= n) %= MOD;
  }
  return ret;
}

// 逆元を求める
ll modinv(ll n) { return modpow(n, MOD - 2); }

// 階乗を求める。O(1)  準備O( n*log(n) )
// fact[n]     : nの階乗
// fact.inv[n] : nの階乗の逆元
class FACTORIAL {
public:
  vector<ll> fact, inv;
  FACTORIAL(int MAX_NUM) : fact(MAX_NUM), inv(MAX_NUM) {
    fact[0] = inv[0] = 1;
    for (ll i = 1; i < MAX_NUM; i++) {
      fact[i] = (fact[i - 1] * i) % MOD;
      inv[i] = modinv(fact[i]);
    }
  }
  const ll &operator[](const int i) const { return fact[i]; }
} fact(10006); // nの最大値を指定

// 組み合わせ(Combinationを求める) O(1)
ll cmb(unsigned int n, unsigned int r) {
  if (n < r)
    return 0;
  return fact[n] * fact.inv[r] % MOD * fact.inv[n - r] % MOD;
}

ll dp[4005][4005] = {};
ll dp2[4005][4005] = {};
int main() {
  // ios_base::sync_with_stdio(false);
  ll N, K, ans = 0;

  cin >> N >> K;

  dp[0][0] = 1;
  rep(i, 2 * N) rep(j, 2 * N) {
    dp[i][j] %= MOD;
    dp[i + 2][j + 1] += dp[i][j];
    dp[i + 1][j + 0] += dp[i][j];
  }
  // rep(i,2*N){
  // 	rep(j,2*N) cout << dp[i][j] << " ";
  // 	cout << endl;
  // }

  dp2[0][0] = 1;
  rep(i, 2 * K) {
    rep(j, 2 * N) dp2[i + 1][j] += dp2[i][j];
    rep(j, N) {
      // int m = (N - 1 - i) / K;
      int m = (N - 1 - i) / K;
      if (i >= K)
        m = (N - 1 - i + K) / K;
      reps(k, 1, m + 1) {
        dp2[i + 1][j + k] += dp2[i][j] * dp[m + 1][k];
        dp2[i + 1][j + k] %= MOD;
      }
    }
  }
  // rep(i,N+N) cout << dp2[2*K][i] << ", ";
  // cout << endl;

  rep(i, N + N) {
    ans += MOD;
    ans += dp2[2 * K][i] * (i % 2 ? -1 : +1) * fact[N - i];
    ans %= MOD;
    // cout << i << " : " << dp2[2*K][i] * (i%2 ? -1 : +1) * fact[N - i] <<
    // endl;
  }

  cout << ans << endl;

  return 0;
}