Problem p03989 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
const ll mod = 924844033;
template <ll mod, ll primitiveroot> struct NumberTheoreticTransform {
  vector<vector<ll>> rts, rrts;
  void ensure_base(ll N) {
    if (rts.size() >= N)
      return;
    rts.resize(N), rrts.resize(N);
    for (ll i = 1; i < N; i <<= 1) {
      if (rts[i].size())
        continue;
      ll w = mod_pow(primitiveroot, (mod - 1) / (i * 2));
      ll rw = inverse(w);
      rts[i].resize(i), rrts[i].resize(i);
      rts[i][0] = 1, rrts[i][0] = 1;
      for (ll k = 1; k < i; k++) {
        rts[i][k] = mul(rts[i][k - 1], w);
        rrts[i][k] = mul(rrts[i][k - 1], rw);
      }
    }
  }

  inline ll mod_pow(ll x, ll n) {
    ll ret = 1;
    while (n > 0) {
      if (n & 1)
        ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline ll inverse(ll x) { return mod_pow(x, mod - 2); }

  inline ll add(ll x, ll y) {
    x += y;
    if (x >= mod)
      x -= mod;
    return x;
  }

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

  void DiscreteFourierTransform(vector<ll> &F, bool rev) {
    const ll N = (ll)F.size();
    ensure_base(N);
    for (ll i = 0, j = 1; j + 1 < N; j++) {
      for (ll k = N >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(F[i], F[j]);
    }
    for (ll i = 1; i < N; i <<= 1) {
      for (ll j = 0; j < N; j += i * 2) {
        for (ll k = 0; k < i; k++) {
          ll s = F[j + k], t = mul(F[j + k + i], rev ? rrts[i][k] : rts[i][k]);
          F[j + k] = add(s, t), F[j + k + i] = add(s, mod - t);
        }
      }
    }
    if (rev) {
      ll temp = inverse(N);
      for (ll i = 0; i < N; i++)
        F[i] = mul(F[i], temp);
    }
  }

  vector<ll> Multiply(const vector<ll> &A, const vector<ll> &B) {
    ll sz = 1;
    while (sz < A.size() + B.size() - 1)
      sz <<= 1;
    vector<ll> F(sz), G(sz);
    for (ll i = 0; i < A.size(); i++)
      F[i] = A[i];
    for (ll i = 0; i < B.size(); i++)
      G[i] = B[i];
    DiscreteFourierTransform(F, false);
    DiscreteFourierTransform(G, false);
    for (ll i = 0; i < sz; i++)
      F[i] = mul(F[i], G[i]);
    DiscreteFourierTransform(F, true);
    F.resize(A.size() + B.size() - 1);
    return F;
  }
};

ll oneline[4005][2005];
ll N, K;
vector<ll> dp;
ll SIZE = 1;
ll Factorial[4005];
int main() {
  // cout.precision(10);
  cin.tie(0);
  ios::sync_with_stdio(false);
  NumberTheoreticTransform<mod, 5> NNT;
  dp.push_back(1);
  cin >> N >> K;
  for (int i = 0; i <= 4000; i++)
    oneline[i][0] = 1;
  for (int len = 1; len <= 2 * N; len++) {
    for (int num = 1; num <= N; num++) {
      if (len >= 2)
        oneline[len][num] =
            (oneline[len - 2][num - 1] + oneline[len - 1][num]) % mod;
      else
        oneline[len][num] = oneline[len - 1][num - 1];
      // cerr << len << " " << num << " " << oneline[len][num] << endl;
    }
  }
  for (ll k = 1; k <= K; k++) {
    ll len = ((N - k) / K + 1) - 1;
    ll NOWSIZE = 0;
    while (oneline[len][NOWSIZE + 1] != 0)
      NOWSIZE++;
    vector<ll> now;
    for (int i = 0; i <= NOWSIZE; i++)
      now.push_back(oneline[len][i]);
    dp = NNT.Multiply(dp, now);
    dp = NNT.Multiply(dp, now);
    /*
    for(int i = 0; i <= SIZE + NOWSIZE; i++) {
        dpnext[i] = 0;
        for(int j = 0; j <= SIZE; j++) {
            if(j > i) break;
            dpnext[i] = (dpnext[i] + dp[j] * oneline[len][i-j]) % mod;
        }
    }
    SIZE += NOWSIZE;
    swap(dpnext, dp);
    for(int i = 0; i <= SIZE + NOWSIZE; i++) {
        dpnext[i] = 0;
        for(int j = 0; j <= SIZE; j++) {
            if(j > i) break;
            dpnext[i] = (dpnext[i] + dp[j] * oneline[len][i-j]) % mod;
        }
    }
    SIZE += NOWSIZE;
    swap(dpnext, dp);
    */
  }
  // for(int i = 0; i <= SIZE; i++) cerr << i << " " << dp[i] << endl;
  Factorial[0] = 1;
  for (ll i = 1; i <= N; i++) {
    Factorial[i] = (Factorial[i - 1] * i) % mod;
  }
  ll ans = 0;
  ll factor = -1;
  for (ll i = 0; i <= N; i++) {
    factor *= -1;
    // cerr << i << " " << factor * Factorial[N-i] * dp[i] << endl;
    ans += factor * Factorial[N - i] * dp[i];
    ans %= mod;
    ans += mod;
    ans %= mod;
  }
  cout << ans << endl;
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
const ll mod = 924844033;
template <ll mod, ll primitiveroot> struct NumberTheoreticTransform {
  vector<vector<ll>> rts, rrts;
  void ensure_base(ll N) {
    if (rts.size() >= N)
      return;
    rts.resize(N), rrts.resize(N);
    for (ll i = 1; i < N; i <<= 1) {
      if (rts[i].size())
        continue;
      ll w = mod_pow(primitiveroot, (mod - 1) / (i * 2));
      ll rw = inverse(w);
      rts[i].resize(i), rrts[i].resize(i);
      rts[i][0] = 1, rrts[i][0] = 1;
      for (ll k = 1; k < i; k++) {
        rts[i][k] = mul(rts[i][k - 1], w);
        rrts[i][k] = mul(rrts[i][k - 1], rw);
      }
    }
  }

  inline ll mod_pow(ll x, ll n) {
    ll ret = 1;
    while (n > 0) {
      if (n & 1)
        ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline ll inverse(ll x) { return mod_pow(x, mod - 2); }

  inline ll add(ll x, ll y) {
    x += y;
    if (x >= mod)
      x -= mod;
    return x;
  }

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

  void DiscreteFourierTransform(vector<ll> &F, bool rev) {
    const ll N = (ll)F.size();
    ensure_base(N);
    for (ll i = 0, j = 1; j + 1 < N; j++) {
      for (ll k = N >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(F[i], F[j]);
    }
    for (ll i = 1; i < N; i <<= 1) {
      for (ll j = 0; j < N; j += i * 2) {
        for (ll k = 0; k < i; k++) {
          ll s = F[j + k], t = mul(F[j + k + i], rev ? rrts[i][k] : rts[i][k]);
          F[j + k] = add(s, t), F[j + k + i] = add(s, mod - t);
        }
      }
    }
    if (rev) {
      ll temp = inverse(N);
      for (ll i = 0; i < N; i++)
        F[i] = mul(F[i], temp);
    }
  }

  vector<ll> Multiply(const vector<ll> &A, const vector<ll> &B) {
    ll sz = 1;
    while (sz < A.size() + B.size() - 1)
      sz <<= 1;
    vector<ll> F(sz), G(sz);
    for (ll i = 0; i < A.size(); i++)
      F[i] = A[i];
    for (ll i = 0; i < B.size(); i++)
      G[i] = B[i];
    DiscreteFourierTransform(F, false);
    DiscreteFourierTransform(G, false);
    for (ll i = 0; i < sz; i++)
      F[i] = mul(F[i], G[i]);
    DiscreteFourierTransform(F, true);
    F.resize(A.size() + B.size() - 1);
    return F;
  }
};

ll oneline[4005][2005];
ll N, K;
vector<ll> dp;
ll SIZE = 1;
ll Factorial[4005];
int main() {
  // cout.precision(10);
  cin.tie(0);
  ios::sync_with_stdio(false);
  NumberTheoreticTransform<mod, 5> NNT;
  dp.push_back(1);
  cin >> N >> K;
  for (int i = 0; i <= 4000; i++)
    oneline[i][0] = 1;
  for (int len = 1; len <= 2 * N; len++) {
    for (int num = 1; num <= N; num++) {
      if (len >= 2)
        oneline[len][num] =
            (oneline[len - 2][num - 1] + oneline[len - 1][num]) % mod;
      else
        oneline[len][num] = oneline[len - 1][num - 1];
      // cerr << len << " " << num << " " << oneline[len][num] << endl;
    }
  }
  for (ll k = 1; k <= K; k++) {
    ll len = ((N - k) / K + 1) - 1;
    ll NOWSIZE = 0;
    while (oneline[len][NOWSIZE + 1] != 0)
      NOWSIZE++;
    vector<ll> now;
    for (int i = 0; i <= NOWSIZE; i++)
      now.push_back(oneline[len][i]);
    dp = NNT.Multiply(dp, now);
    dp = NNT.Multiply(dp, now);
    /*
    for(int i = 0; i <= SIZE + NOWSIZE; i++) {
        dpnext[i] = 0;
        for(int j = 0; j <= SIZE; j++) {
            if(j > i) break;
            dpnext[i] = (dpnext[i] + dp[j] * oneline[len][i-j]) % mod;
        }
    }
    SIZE += NOWSIZE;
    swap(dpnext, dp);
    for(int i = 0; i <= SIZE + NOWSIZE; i++) {
        dpnext[i] = 0;
        for(int j = 0; j <= SIZE; j++) {
            if(j > i) break;
            dpnext[i] = (dpnext[i] + dp[j] * oneline[len][i-j]) % mod;
        }
    }
    SIZE += NOWSIZE;
    swap(dpnext, dp);
    */
  }
  // for(int i = 0; i <= SIZE; i++) cerr << i << " " << dp[i] << endl;
  Factorial[0] = 1;
  for (ll i = 1; i <= N; i++) {
    Factorial[i] = (Factorial[i - 1] * i) % mod;
  }
  ll ans = 0;
  ll factor = -1;
  for (ll i = 0; i <= N; i++) {
    if (i >= dp.size())
      break;
    factor *= -1;
    // cerr << i << " " << factor * Factorial[N-i] * dp[i] << endl;
    ans += factor * Factorial[N - i] * dp[i];
    ans %= mod;
    ans += mod;
    ans %= mod;
  }
  cout << ans << endl;
  return 0;
}