//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#ifndef LOCAL
#pragma GCC optimize("O3")
#endif
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define st first
#define nd second

using namespace __gnu_pbds;
using namespace std;
 
template <typename T>
using ordered_set =
	tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
 
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
 
#define shandom_ruffle random_shuffle
 
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;

const int MAXN = 5100;

//~ int binom[MAXN][MAXN];

int n, mod;
int vals[MAXN];
int brute_ans;

void Check() {

	bool mycheck = vals[0] + vals[1] > vals[n-1];
	
	int suml = vals[0], sumr = 0;
	for (int len = 1; len < n; ++len) {
		suml += vals[len];
		sumr += vals[n - len];
		if (sumr >= suml) {
			if (mycheck) {
				for (int i = 0; i < n; ++i) {
					cout << vals[i] << " ";
				}
				cout << "\n";
			}
			return;
		}
	}
	++brute_ans;
}

void Brute(int idx, int minval) {
	if (idx == n) { return Check(); }
	for (int a = minval; a <= n; ++a) {
		vals[idx] = a;
		Brute(idx + 1, a);
	}
}

int dp_pairs[2][MAXN][MAXN];
int prefsum[MAXN][MAXN];

void Preproc() {
	const int k = (n - 1) / 2;

	if (n % 2 == 0) {
		for (int d = 0; d <= n; ++d) {
			dp_pairs[1][d][d] = d + 1;
		}
	} else {
		for (int d = 0; d <= n; ++d) {
			dp_pairs[1][d][d] = 1;
		}
	}
	
	for (int idx = 2; idx <= k; ++idx) {
		const int from = (idx - 1) % 2, to = idx % 2;

		for (int sum = 0; sum <= n; ++sum) {
			dp_pairs[to][0][sum] = dp_pairs[from][0][sum];
			prefsum[0][sum] = dp_pairs[from][0][sum];
		}

		for (int cur = 1; cur * (k - (idx-1)) <= n; ++cur) {
			for (int sum = 0; sum <= n; ++sum) {
				int &dpref = prefsum[cur][sum];
				dpref = prefsum[cur-1][sum] + dp_pairs[from][cur][sum];
				if (dpref >= mod) { dpref -= mod; }
				int &dest = dp_pairs[from][cur][sum];
				dest = prefsum[cur][sum] + dp_pairs[from][cur-1][sum];
				if (dest >= mod) { dest -= mod; }
				debug() << idx << " " << cur << " " << sum << " " << imie(dpref) << imie(dest);
			}
		}
		
		for (int cur = 1; cur * (k - idx) <= n && cur <= n; ++cur) {
			memset(dp_pairs[to][cur], 0, sizeof(dp_pairs[to][cur]));

			for (int sum = cur; sum <= n; ++sum) {
				dp_pairs[to][cur][sum] = dp_pairs[from][cur][sum-cur];
				debug() << "!" << to << " " << cur << " " << sum << " : " <<
					dp_pairs[to][cur][sum];
			}
		}
	}

	if (k % 2 == 1) {
		memcpy(dp_pairs[0], dp_pairs[1], sizeof(dp_pairs[1]));
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout << fixed << setprecision(11);
	cerr << fixed << setprecision(6);
	
	cin >> n >> mod;
	if (n == 2) {
		cout << "3\n";
		return 0;
	}

	//~ Brute(0, 1);
	//~ cout << brute_ans << "\n";
	//~ return 0;

	//~ binom[0][0] = 1;
	//~ for (int i = 1; i <= 2 * n; ++i) {
		//~ binom[i][0] = 1;
		//~ for (int j = 1; j <= i; ++j) {
			//~ binom[i][j] = (binom[i-1][j] + binom[i-1][j-1]) % mod;
		//~ }
	//~ }

	Preproc();

	for (int i = 0; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			dp_pairs[0][i][j] += dp_pairs[0][i][j-1];
			if (dp_pairs[0][i][j] >= mod) {
				dp_pairs[0][i][j] -= mod;
			}
		}
	}
	
	int ans = 0;
	for (int a1 = 1; a1 <= n; ++a1) {
		for (int span = 0; a1 + span <= n; ++span) {
			int x = dp_pairs[0][span][a1-1];
			//~ for (int i = 0; i < a1; ++i) {
				//~ x = (x + dp_pairs[0][span][i]) % mod;
			//~ }
			debug() << imie(a1) << imie(span) << imie(x);
			const int num_ways = n - (a1 + span) + 1;
			ans = (ans + (ll)x * num_ways) % mod;
		}
	}
	cout << ans << "\n";
}


Measured memory_bytes: 303360