枚举每条边的贡献来进行统计。
树上统计的常用方法:用边将树分割成两个部分。
#include <bits/stdc++.h>
using namespace std;
typedef int lint;
typedef long long LL;
const int maxn = 2005;
int mod;
LL C[maxn][maxn],frac[maxn],dp[maxn][maxn];
lint ad( LL x,LL y ){
x += y;
if( x > mod ) x-= mod;
return x;
}
lint mul( LL x,LL y ){
x *= y;
x %= mod;
return x;
}
void init( lint n ){
for( lint i = 0;i <= n;i++ )C[i][0] = 1;
for( lint i = 1;i <= n;i++ ){
for( lint j = 1;j <= n;j++ ){
C[i][j] = (C[i-1][j-1] + C[i-1][j])%mod;
}
}
frac[0] = 1;
for( lint i = 1;i <= n;i++ ){
frac[i] = frac[i-1]*i%mod;
}
}
int main(){
lint n;
scanf("%d%d",&n,&mod);
init(n);
if( n == 1 ){
printf("0");
return 0;
}
LL ans = 0;
dp[0][0] = 1;
for( lint i = 1;i <= n;i++ ){
dp[i][i] = i;
for( lint j = i+1;j <= n;j++ ){
dp[i][j] = dp[i][j-1]*j%mod;
}
}
for( lint i = 2;i <= n;i++ ){
for( lint siz = 0;siz <= n-i;siz++ ){
ans = ad( ans,mul( (LL)(siz+1)*( n-siz-1 )%mod,C[n-i][siz]*frac[siz+1]%mod*frac[i]%mod * ((i-1 <= n-siz-2)?dp[i-1][ n-siz-2 ]:1)%mod ) );
}
}
cout << ans;
return 0;
}