/*
	字典序大小关系，即第一个不同的字符大小关系。

	枚举长度i、p第一个字符j、q第一个字符k，这两个字符本身产生的逆序对数差已知，因此对后i-1个字符有一个逆序对数差的下限要求，考虑怎么预处理这一块做到O1使整个复杂度为三方。

	四方暴力DP：f_i_j表示长度为i、逆序对数差为j的两个排列有多少种，枚举n插入位置差可以知道逆序对数该变量。

	前缀和优化转移，复杂度三方。数组滚动，空间复杂度平方。
*/
#include <bits/stdc++.h>
using namespace std ;
const int MaxN = 260000 + 10 ;
const int B = 130000 ;
int N , Mod , Dp[2][MaxN] , S[2][MaxN] , Ans[MaxN] ;
int main() {
	cin >> N >> Mod ;
	for(int i = 1 ; i <= N ; ++i ) {
		int Bit = i & 1 , Inv = Bit ^ 1 , M = i*(i-1)>>1 ;
		S[Inv][0] = Dp[Inv][0] ;
		for(int j = 1 ; j <= 260000 ; ++j )
			S[Inv][j] = ( S[Inv][j-1] + Dp[Inv][j] ) % Mod ;
		memset( Dp[Bit] , 0 , sizeof Dp[Bit] ) ;
		Dp[Bit][B-M] = 1 ;
		for(int j = -M ; j < M ; ++j )
			Dp[Bit][B+j+1] = ( 0ll + Dp[Bit][B+j] + Mod - S[Inv][B+j] + S[Inv][B+j-i] + S[Inv][B+j+i] + Mod - S[Inv][B+j] ) % Mod ;
		for(int j = 1 ; j < i ; ++j )
			Ans[i] = ( Ans[i] + 1ll * (i-j) * (S[Inv][B+M]-S[Inv][B+j]) ) % Mod ;
	}
	for(int i = 2 ; i <= N ; ++i )
		Ans[i] = ( Ans[i] + 1ll * i * Ans[i-1] ) % Mod ;
	return not printf( "%d\n" , (Ans[N]+Mod)%Mod ) ;
}