//ProblemD.cpp

#include <iostream>

static std::istream & ip = std::cin;
static std::ostream & op = std::cout;

#if OJ_MYPC
#include <ojio.h>
#endif

#ifndef OPENOJIO
#define OPENOJIO
#endif

#if 1 || DEFINE
/***************************************************************/
typedef unsigned long long u64;
typedef long long s64;

typedef unsigned uint;

#define ABS(x) ((x) > 0 ? (x) : -(x))

#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))

#define MIN3(x, y, z) MIN(x, MIN(y, z))
#define MAX3(x, y, z) MAX(x, MAX(y, z))

#define FillZero(arr) memset(arr, 0, sizeof(arr));

/***************************************************************/
#endif //1 || DEFINE

#include <string>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <utility>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <assert.h>

//001
//op << setfill('0') << setw(3) << setiosflags(ios::right) << 1;

//op << fixed << setprecision(20);

using namespace std;

//ProblemD.cpp

#define MAXN 2010
#define MOD 924844033LL

//gcdex = ax + by
template <typename Int>
Int gcdex(Int a, Int b, Int& x, Int& y)
{
	bool swapped = false;

	if (a < b) { swap(a, b); swapped = true; }
	Int rst = 0;

	if (a % b == 0) { x = 0; y = 1; rst = b; }
	else
	{
		Int tx, ty;
		rst = gcdex(b, a % b, tx, ty);

		x = ty;
		y = tx - ty * (a / b);
	}

	if (swapped) swap(x, y);
	return rst;
}

int main(int argc, char* argv[])
{
	OPENOJIO;

	int n, k;
	ip >> n >> k;

	s64 rst = 0;

	s64 fac[MAXN];
	fac[0] = fac[1] = 1;
	for (int i = 2; i <= n; ++i) {
		fac[i] = fac[i - 1] * i % MOD;
	}

	s64 inv[MAXN];
	inv[1] = 1;
	for (s64 i = 2; i <= n; ++i) {
		s64 tmp;
		gcdex(MOD, i, tmp, inv[i]);
		inv[i] = ((inv[i] % MOD) + MOD) % MOD;

		assert((inv[i] * i) % MOD == 1);
	}

	s64 inv_fac[MAXN];
	inv_fac[0] = inv_fac[1] = 1;
	for (int i = 2; i <= n; ++i) {
		inv_fac[i] = inv_fac[i - 1] * inv[i] % MOD;

		assert((fac[i] * inv_fac[i]) % MOD == 1);
	}


	int path_length = (n - 1) / k;
	s64 p1 = path_length, p2 = p1 - 1;

	s64 comb1[MAXN], comb2[MAXN];
	FillZero(comb1); FillZero(comb2);
	for (int i = 0; i <= p1 - i + 1; ++i) {
		comb1[i] = fac[p1 - i + 1] * inv_fac[i] % MOD * inv_fac[p1 - 2 * i + 1] % MOD;
		//comb[i] = C(p1 - i + 1, i)
	}
	for (int i = 0; i <= p2 - i + 1; ++i) {
		comb2[i] = fac[p2 - i + 1] * inv_fac[i] % MOD * inv_fac[p2 - 2 * i + 1] % MOD;
		//comb2[i] = C(p1 - i + 1, i)
	}

	s64 dp[2][MAXN];
	FillZero(dp);
	dp[0][0] = 1;

	int ndp = 1;
	for (int i = 0; i < k; ++i) {
		int t_path_length = (n - (i + 1)) / k;
		const s64 *comb = t_path_length == p1 ? comb1 : comb2;

		for (int loop = 0; loop < 2; ++loop) {
			s64 *dpp = dp[1 - ndp];
			s64 *dpn = dp[ndp];

			for (int j = 0; j <= n; ++j)
			{
				dpn[j] = 0;
				for (int j2 = 0; j2 <= MIN(j, t_path_length); ++j2) {
					dpn[j] += comb[j2] * dpp[j - j2];
					dpn[j] %= MOD;
				}
			}

			ndp = 1 - ndp;
		}
	}

	s64* dpf = dp[1 - ndp];
	s64 sign = 1;

	for (int i = 0; i <= n; ++i) {
		rst += sign * fac[n - i] * dpf[i];
		rst = ((rst % MOD) + MOD) % MOD;

		sign = -sign;
	}

	op << rst << endl;

	return 0;
}
/***************************************************************/


Measured memory_bytes: 512